lib/extender/taggable.rb
# encoding: utf-8
module Extender
module Taggable
def self.included(base)
base.send :include, InstanceMethods
base.extend ClassMethods
base.relate
end
module ClassMethods
def relate
has_many :tag_rels, :as => :taggable, :dependent => :destroy
has_many :tags, :through=> :tag_rels
accepts_nested_attributes_for :tags
before_destroy :decrement_tags_counter
validates :tagnames, :presence => true
validate :check_tags
before_save :set_tags
def grouped_tags(thr)
joins(:tags).
where(:tags=>{:name.matches_any=> thr.tags.map(&:name) }).
group("tags.name").count(:id)
end
end
end
module InstanceMethods
def check_tags
unless self.tagnames.nil?
# first tag must be in special tags array
# unless Tag::SPECIAL_TAGS.include? tags_array_from_string.first
# errors.add(:tagnames,:no_special_tags,:arr=>Tag::SPECIAL_TAGS.join(', '))
# end
# check tags count
if tags_array_from_string.count < Tag::MIN_TAGS || tags_array_from_string.count > Tag::MAX_TAGS
errors.add(:tagnames,:min_max_tags,:min=>Tag::MIN_TAGS.to_s,:max=>Tag::MAX_TAGS.to_s)
end
end
end
def set_tags
return unless self.tagnames
tags_arr = tags_array_from_string
self.tagnames = tags_arr.join(' ')
return unless self.tagnames_changed?
decrement_tags_counter
self.tag_rels.destroy_all
tags_arr.each do |tagname|
tag = Tag.active.find_or_initialize_by_name(tagname)
if tag.new_record? #
tag.user_id = user_id
tag.increment(:quantity)
unless tag.save
errors.add(:tagnames,"zawiera słowo \"#{tagname}\", które #{tag.errors.first.last}")
return false
end
else
tag.increment!(:quantity)
end
self.tag_rels.build(:tag_id=>tag.id)
end
end
def decrement_tags_counter
self.tags.each { |tag| tag.decrement!(:quantity) }
end
def tags_array_from_string
self.tagnames.downcase.gsub(tag_sanitize_pattern,"").split(' ').uniq
end
def tag_sanitize_pattern
/[^0-9a-zA-Z\- ]+/i
end
end
end
end