Skip to content

Instantly share code, notes, and snippets.

@christianhellsten
Created September 29, 2010 18:30
Show Gist options
  • Save christianhellsten/603265 to your computer and use it in GitHub Desktop.
Save christianhellsten/603265 to your computer and use it in GitHub Desktop.
Tag ActiveRecord models
module Taggable
def self.included(base)
base.send :include, InstanceMethods
base.extend ClassMethods
end
module ClassMethods
def initialize(collection_names)
delimiter = ','
collection_names.map(&:to_s).each do |collection_name|
owner_name = self.name.downcase
class_name = collection_name.to_s.classify
method_name = collection_name.to_s.singularize
has_many_name = [owner_name, collection_name].sort
has_many_name = [has_many_name.first.singularize, has_many_name.last.pluralize].join('_').to_sym
class_eval do
before_save :"set_#{collection_name}"
has_many has_many_name, :dependent => :destroy
has_many collection_name, :through => has_many_name
end
code = %(
def #{method_name}_list
@#{method_name}_list ||= self.#{collection_name}.collect(&:name)
@#{method_name}_list.join('#{delimiter} ')
end
def #{method_name}_list=(#{method_name}_names)
return if #{method_name}_names.blank?
@#{method_name}_list = #{method_name}_names.split('#{delimiter}').collect(&:strip).uniq.reject(&:blank?)
@#{method_name}_list
end
def set_#{collection_name}
return if @#{method_name}_list.nil?
existing = self.#{collection_name}.map(&:name)
self.#{collection_name} = []
@#{method_name}_list.each do |#{method_name}_name|
self.#{collection_name} << #{class_name}.find_or_create_by_name(#{method_name}_name)
end
end
)
class_eval code
end
end
def taggable(*args)
initialize(args)
end
end
module InstanceMethods
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment