# encoding: UTF-8 require "stringex/acts_as_url/adapter" module Stringex module ActsAsUrl # :nodoc: def self.configure(&block) Stringex::Configuration::ActsAsUrl.configure &block end def self.unconfigure! Stringex::Configuration::ActsAsUrl.unconfigure! end module ActsAsUrlClassMethods # :doc: # Creates a callback to automatically create an url-friendly representation # of the attribute argument. Example: # # acts_as_url :title # # will use the string contents of the title attribute # to create the permalink. Note: you can also use a non-database-backed # method to supply the string contents for the permalink. Just use that method's name # as the argument as you would an attribute. # # The default attribute acts_as_url uses to save the permalink is url # but this can be changed in the options hash. Available options are: # # :adapter:: If specified, will indicate what ORM adapter to use. Default functionality # is to use the first available adapter. This should work for most cases # unless you are using multiple ORMs in a single project. # :allow_slash:: If true, allows the generated url to contain slashes. Default is false[y]. # :allow_duplicates:: If true, allows duplicate urls instead of appending numbers to # differentiate between urls. Default is false[y]. See note on :scope. # :duplicate_count_separator:: String to use when forcing unique urls from non-unique strings. # Default is "-". # :force_downcase:: If false, allows generated url to contain uppercased letters. Default is false. # :exclude_list:: List of complete strings that should not be transformed by acts_as_url. # Default is empty. # :only_when_blank:: If true, the url generation will only happen when :url_attribute is # blank. Default is false[y] (meaning url generation will happen always). # :scope:: The name of model attribute to scope unique urls to. There is no default here. # Note: this will automatically act as if :allow_duplicates # is set to true. # :sync_url:: If set to true, the url field will be updated when changes are made to the # attribute it is based on. Default is false. # :url_attribute:: The name of the attribute to use for storing the generated url string. # Default is :url. # :limit:: The maximum size a generated url should be. Note: this does not # include the characters needed to enforce uniqueness on duplicate urls. # Default is nil. def acts_as_url(attribute, options = {}) class_eval do class << self attr_accessor :acts_as_url_configuration end define_method :acts_as_url_configuration do klass = self.class while klass.acts_as_url_configuration.nil? klass = klass.superclass end klass.acts_as_url_configuration end end options[:attribute_to_urlify] = attribute self.acts_as_url_configuration = Stringex::Configuration::ActsAsUrl.new(options) acts_as_url_configuration.adapter.create_callbacks! self end # Some ORMs function as mixins not base classes and need to have a hook to reinclude # and re-extend ActsAsUrl methods def included(base) super base.send :include, Stringex::ActsAsUrl::ActsAsUrlInstanceMethods base.send :extend, Stringex::ActsAsUrl::ActsAsUrlClassMethods end # Initialize the url fields for the records that need it. Designed for people who add # acts_as_url 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 acts_as_url_configuration.adapter.initialize_urls! self end end module ActsAsUrlInstanceMethods def ensure_unique_url acts_as_url_configuration.adapter.ensure_unique_url! self end end end end