module Acts
  module Sluggable
    module ClassMethods
      #
      # Adds the logic to generate the slug
      #
      # Options:
      #
      #   :generate_from
      #       The name of the field used to generate the slug
      #
      #   :store_as
      #       The name of the field where the slug will be stored
      #
      def acts_as_sluggable(options = {})
        options = {
          :generate_from => :name,
          :store_as => :slug
        }.merge(options)

        class_eval do
          before_save do
            generate_slug(options[:generate_from], options[:store_as])
          end
          field(options[:store_as], :type => String) unless self.respond_to?(options[:store_as])
          index(options[:store_as])
          alias_method :to_param!, :to_param
        end

        define_method("to_param") do
          self.send(options[:store_as])
        end
      end
    end

    module InstanceMethods
      def generate_slug(method, slug_field_name)
        self.send("#{slug_field_name.to_s}=", self.send(method).parameterize)
      end
    end

    def self.included(receiver)
      receiver::ClassMethods.send :include, ClassMethods
      receiver.send :include, InstanceMethods
    end
  end
end