Skip to content

Commit

Permalink
rearrange plugin modules so not all AR models contain the custom perm…
Browse files Browse the repository at this point in the history
…alink options
  • Loading branch information
technoweenie committed Sep 4, 2008
1 parent 96835e1 commit e2b20d5
Showing 1 changed file with 78 additions and 60 deletions.
138 changes: 78 additions & 60 deletions lib/permalink_fu.rb
Expand Up @@ -9,27 +9,24 @@ module PermalinkFu
class << self
attr_accessor :translation_to
attr_accessor :translation_from


# This method does the actual permalink escaping.
def escape(str)
s = ((translation_to && translation_from) ? Iconv.iconv(translation_to, translation_from, str) : str).to_s
s.gsub!(/[^\w -]+/, '') # strip unwanted characters
s.strip! # ohh la la
s.downcase! #
s.gsub!(/[ -]+/, '-') # separate by single dashes
s.strip! # ohh la la
s.downcase! #
s.gsub!(/[ -]+/, '-') # separate by single dashes
s
end
end

def self.included(base)
base.extend ClassMethods
class << base
attr_accessor :permalink_options
attr_accessor :permalink_attributes
attr_accessor :permalink_field
end
base.extend PluginMethods
end

module ClassMethods

# This is the plugin method available on all ActiveRecord models.
module PluginMethods
# Specifies the given field(s) as a permalink, meaning it is passed through PermalinkFu.escape and set to the permalink_field. This
# is done
#
Expand All @@ -56,67 +53,88 @@ def has_permalink(attr_names = [], permalink_field = nil, options = {})
options = permalink_field
permalink_field = nil
end
extend ClassMethods
self.permalink_attributes = Array(attr_names)
self.permalink_field = (permalink_field || 'permalink').to_s
self.permalink_options = options
before_validation :create_unique_permalink
evaluate_attribute_method permalink_field, "def #{self.permalink_field}=(new_value);write_attribute(:#{self.permalink_field}, PermalinkFu.escape(new_value));end", "#{self.permalink_field}="
setup_permalink_fu
end
end

protected
def create_unique_permalink
return unless should_create_permalink?
if send(self.class.permalink_field).to_s.empty?
send("#{self.class.permalink_field}=", create_permalink_for(self.class.permalink_attributes))
end
limit = self.class.columns_hash[self.class.permalink_field].limit
base = send("#{self.class.permalink_field}=", send(self.class.permalink_field)[0..limit - 1])
counter = 1
# oh how i wish i could use a hash for conditions
conditions = ["#{self.class.permalink_field} = ?", base]
unless new_record?
conditions.first << " and id != ?"
conditions << id
end
if self.class.permalink_options[:scope]
scopes = [self.class.permalink_options[:scope]]
scopes.flatten!
scopes.each do |scope|
conditions.first << " and #{scope} = ?"
conditions << send(scope)

# Contains class methods for ActiveRecord models that have permalinks
module ClassMethods
def self.extended(base)
class << base
attr_accessor :permalink_options
attr_accessor :permalink_attributes
attr_accessor :permalink_field
end
base.send :include, InstanceMethods
end
while self.class.exists?(conditions)
suffix = "-#{counter += 1}"
conditions[1] = "#{base[0..limit-suffix.size-1]}#{suffix}"
send("#{self.class.permalink_field}=", conditions[1])

protected
def setup_permalink_fu
before_validation :create_unique_permalink
evaluate_attribute_method permalink_field, "def #{self.permalink_field}=(new_value);write_attribute(:#{self.permalink_field}, PermalinkFu.escape(new_value));end", "#{self.permalink_field}="
end
end

def create_permalink_for(attr_names)
attr_names.collect { |attr_name| send(attr_name).to_s } * " "
end
# This contains instance methods for ActiveRecord models that have permalinks.
module InstanceMethods
protected
def create_unique_permalink
return unless should_create_permalink?
if send(self.class.permalink_field).to_s.empty?
send("#{self.class.permalink_field}=", create_permalink_for(self.class.permalink_attributes))
end
limit = self.class.columns_hash[self.class.permalink_field].limit
base = send("#{self.class.permalink_field}=", send(self.class.permalink_field)[0..limit - 1])
counter = 1
# oh how i wish i could use a hash for conditions
conditions = ["#{self.class.permalink_field} = ?", base]
unless new_record?
conditions.first << " and id != ?"
conditions << id
end
if self.class.permalink_options[:scope]
scopes = [self.class.permalink_options[:scope]]
scopes.flatten!
scopes.each do |scope|
conditions.first << " and #{scope} = ?"
conditions << send(scope)
end
end
while self.class.exists?(conditions)
suffix = "-#{counter += 1}"
conditions[1] = "#{base[0..limit-suffix.size-1]}#{suffix}"
send("#{self.class.permalink_field}=", conditions[1])
end
end

private
def should_create_permalink?
if self.class.permalink_options[:if]
evaluate_method(self.class.permalink_options[:if])
elsif self.class.permalink_options[:unless]
!evaluate_method(self.class.permalink_options[:unless])
else
true
def create_permalink_for(attr_names)
attr_names.collect { |attr_name| send(attr_name).to_s } * " "
end

private
def should_create_permalink?
if self.class.permalink_options[:if]
evaluate_method(self.class.permalink_options[:if])
elsif self.class.permalink_options[:unless]
!evaluate_method(self.class.permalink_options[:unless])
else
true
end
end
end

def evaluate_method(method)
case method
when Symbol
send(method)
when String
eval(method, instance_eval { binding })
when Proc, Method
method.call(self)
def evaluate_method(method)
case method
when Symbol
send(method)
when String
eval(method, instance_eval { binding })
when Proc, Method
method.call(self)
end
end
end
end
Expand Down

0 comments on commit e2b20d5

Please sign in to comment.