From e2b20d5b5ae793922879559fe2ea7b1674cbfad5 Mon Sep 17 00:00:00 2001 From: rick Date: Wed, 3 Sep 2008 17:50:21 -0700 Subject: [PATCH] rearrange plugin modules so not all AR models contain the custom permalink options --- lib/permalink_fu.rb | 138 +++++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 60 deletions(-) diff --git a/lib/permalink_fu.rb b/lib/permalink_fu.rb index 70c0e6e..ed04824 100644 --- a/lib/permalink_fu.rb +++ b/lib/permalink_fu.rb @@ -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 # @@ -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