module ActsAsTaggableOn module Tagger def self.included(base) base.extend ClassMethods end module ClassMethods ## # Make a model a tagger. This allows an instance of a model to claim ownership # of tags. # # Example: # class User < ActiveRecord::Base # acts_as_tagger # end def acts_as_tagger(opts={}) class_eval do has_many_with_taggable_compatibility :owned_taggings, opts.merge( as: :tagger, dependent: :destroy, class_name: 'ActsAsTaggableOn::Tagging' ) has_many_with_taggable_compatibility :owned_tags, through: :owned_taggings, source: :tag, class_name: 'ActsAsTaggableOn::Tag', uniq: true end include ActsAsTaggableOn::Tagger::InstanceMethods extend ActsAsTaggableOn::Tagger::SingletonMethods end def tagger? false end def is_tagger? tagger? end end module InstanceMethods ## # Tag a taggable model with tags that are owned by the tagger. # # @param taggable The object that will be tagged # @param [Hash] options An hash with options. Available options are: # * :with - The tags that you want to # * :on - The context on which you want to tag # # Example: # @user.tag(@photo, :with => "paris, normandy", :on => :locations) def tag(taggable, opts={}) opts.reverse_merge!(force: true) skip_save = opts.delete(:skip_save) return false unless taggable.respond_to?(:is_taggable?) && taggable.is_taggable? fail 'You need to specify a tag context using :on' unless opts.key?(:on) fail 'You need to specify some tags using :with' unless opts.key?(:with) fail "No context :#{opts[:on]} defined in #{taggable.class}" unless opts[:force] || taggable.tag_types.include?(opts[:on]) taggable.set_owner_tag_list_on(self, opts[:on].to_s, opts[:with]) taggable.save unless skip_save end def tagger? self.class.is_tagger? end def is_tagger? tagger? end end module SingletonMethods def tagger? true end def is_tagger? tagger? end end end end