Navigation Menu

Skip to content

Commit

Permalink
make source optional, add the ability to generate random slugs if no …
Browse files Browse the repository at this point in the history
…source is givien, option to change generation hook to before_validation and also to enforce uniqueness on random generation
  • Loading branch information
kevintom committed Jan 9, 2011
1 parent 4eb2573 commit a9d8ee2
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions lib/sequel_sluggable.rb
Expand Up @@ -8,7 +8,7 @@ module Plugins
# You need to have "target" column in your model.
module Sluggable
DEFAULT_TARGET_COLUMN = :slug

DEFAULT_SLUG_LENGTH = 5
# Plugin configuration
def self.configure(model, opts={})
model.sluggable_options = opts
Expand All @@ -22,10 +22,16 @@ def self.configure(model, opts={})
# @param [String] String to be slugged
# @return [String]
define_method("#{sluggable_options[:target]}=") do |value|
sluggator = self.class.sluggable_options[:sluggator]
slug = sluggator.call(value, self) if sluggator.respond_to?(:call)
slug ||= self.send(sluggator, value) if sluggator
slug ||= to_slug(value)
if value.nil? and self.class.sluggable_options[:random_slug]
slug = random_slug until self.class[sluggable_options[:target] => slug].nil? if self.class.sluggable_options[:unique]
slug ||= random_slug
end
else
sluggator = self.class.sluggable_options[:sluggator]
slug = sluggator.call(value, self) if sluggator.respond_to?(:call)
slug ||= self.send(sluggator, value) if sluggator
slug ||= to_slug(value)
end
super(slug)
end
end
Expand Down Expand Up @@ -66,21 +72,33 @@ def inherited(klass)
# @option source [Symbol] :Column to get value to be slugged from.
# @option target [Symbol] :Column to write value of the slug to.
def sluggable_options=(options)
raise ArgumentError, "You must provide :source column" unless options[:source]
sluggator = options[:sluggator]
if sluggator && !sluggator.is_a?(Symbol) && !sluggator.respond_to?(:call)
raise ArgumentError, "If you provide :sluggator it must be Symbol or callable."
end
options[:source] = options[:source].to_sym
options[:source] = options[:source].to_sym if options[:source]
options[:target] = options[:target] ? options[:target].to_sym : DEFAULT_TARGET_COLUMN
options[:frozen] = options[:frozen].nil? ? true : !!options[:frozen]
options[:slug_lenth] = options[:slug_length] ? options[:slug_length].to_i : DEFAULT_SLUG_LENGTH
options[:random_slug] = options[:source].nil? && options[:sluggator].nil?
options[:unique] = options[:unique].class == TrueClass if options[:unique]
raise ArgumentError, "You must provide :source column" if !options[:random_slug] and options[:source].nil?
options[:before_validate] = options[:before_validate].class == TrueClass if options[:before_validate]
@sluggable_options = options
end
end

module InstanceMethods

# Sets a slug column to the slugged value
def before_validation
super
if self.class.sluggable_options[:before_validate]
target = self.class.sluggable_options[:target]
set_target_column unless self.send(target)
end
end

def before_create
super
target = self.class.sluggable_options[:target]
Expand All @@ -105,12 +123,16 @@ def to_slug(value)
value.chomp.downcase.gsub(/[^a-z0-9]+/,'-')
end

def random_slug
SecureRandom.hex(self.class.sluggable_options[:slug_length])
end

# Sets target column with source column which
# effectively triggers slug generation
def set_target_column
target = self.class.sluggable_options[:target]
source = self.class.sluggable_options[:source]
self.send("#{target}=", self.send(source))
self.send("#{target}=", source ? self.send(source) : nil)
end

end # InstanceMethods
Expand Down

0 comments on commit a9d8ee2

Please sign in to comment.