Created
October 24, 2008 17:02
-
-
Save rsl/19493 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module LuckySneaks | |
module ActsAsUrl # :nodoc: | |
def self.included(base) | |
base.extend ClassMethods | |
end | |
module ClassMethods # :doc: | |
# Creates a callback to automatically create an url-friendly representation | |
# of the <tt>attribute</tt> argument. Example: | |
# | |
# act_as_url :title | |
# | |
# will use the string contents of the <tt>title</tt> attribute | |
# to create the permalink. You may also pass a Proc object instead and this | |
# object will be evaluated and its return value used instead of a database | |
# attribute | |
# | |
# The default attribute <tt>acts_as_url</tt> uses | |
# to store the permalink on the database is <tt>url</tt> but can be changed in the options hash. | |
# Available options are: | |
# | |
# <tt>:url_attribute</tt>:: The name of the attribute to use for storing the generated url string. | |
# Default is <tt>:url</tt> | |
# <tt>:scope</tt>:: The name of model attribute to scope unique urls to. There is no default here. | |
# <tt>:sync_url</tt>:: If set to true, the url field will be updated when changes are made to the | |
# attribute it is based on. Default is false. | |
def acts_as_url(attribute, options = {}) | |
cattr_accessor :attribute_to_urlify | |
cattr_accessor :scope_for_url | |
cattr_accessor :url_attribute # The attribute on the DB | |
if options[:sync_url] | |
before_validation :ensure_unique_url | |
else | |
before_validation_on_create :ensure_unique_url | |
end | |
self.attribute_to_urlify = attribute | |
self.scope_for_url = options[:scope] | |
self.url_attribute = options[:url_attribute] || "url" | |
end | |
# Initialize the url fields for the records that need it. Designed for people who add | |
# <tt>acts_as_url</tt> support once there's already development/production data they'd | |
# like to keep around. | |
# | |
# Note: This method can get very expensive, very fast. If you're planning on using this | |
# on a large selection, you will get much better results writing your own version with | |
# using pagination. | |
def initialize_urls | |
find(:all, :conditions => {self.url_attribute => nil}).each do |instance| | |
instance.send :ensure_unique_url | |
instance.save | |
end | |
end | |
end | |
private | |
def ensure_unique_url | |
url_attribute = self.class.url_attribute | |
base_url = get_base_url | |
conditions = ["#{url_attribute} = ?", base_url] | |
unless new_record? | |
conditions.first << " and id != ?" | |
conditions << id | |
end | |
if self.class.scope_for_url | |
conditions.first << " and #{self.class.scope_for_url} = ?" | |
conditions << send(self.class.scope_for_url) | |
end | |
url_owners = self.class.find(:all, :conditions => conditions) | |
if url_owners.size > 0 | |
n = 1 | |
while url_owners.detect{|u| u.send(url_attribute) == "#{base_url}-#{n}"} | |
n = n.succ | |
end | |
write_attribute url_attribute, "#{base_url}-#{n}" | |
else | |
write_attribute url_attribute, base_url | |
end | |
end | |
def get_base_url | |
if self.class.attribute_to_urlify.is_a?(Proc) | |
instance_exec self, &self.class.attribute_to_urlify | |
else | |
send self.class.attribute_to_urlify | |
end.to_s.to_url | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment