module RedmineCrm module ActsAsTaggable #:nodoc: class Tag < ActiveRecord::Base #:nodoc: has_many :taggings, :dependent => :destroy validates_presence_of :name validates :name, :uniqueness => { :message => " not uniq tag" } validates :name, :presence => true cattr_accessor :destroy_unused self.destroy_unused = false attr_accessible :name if defined?(ActiveModel::MassAssignmentSecurity) # LIKE is used for cross-database case-insensitivity def self.find_or_create_with_like_by_name(name) # find(:first, :conditions => ["name LIKE ?", name]) || create(:name => name) where("LOWER(name) LIKE LOWER(?)", name).first || create(:name => name) end def ==(object) super || (object.is_a?(Tag) && name == object.name) end def to_s name end def count read_attribute(:count).to_i end class << self # Calculate the tag counts for all tags. # :start_at - Restrict the tags to those created after a certain time # :end_at - Restrict the tags to those created before a certain time # :conditions - A piece of SQL conditions to add to the query # :limit - The maximum number of tags to return # :order - A piece of SQL to order by. Eg 'count desc' or 'taggings.created_at desc' # :at_least - Exclude tags with a frequency less than the given value # :at_most - Exclude tags with a frequency greater than the given value def counts(options = {}) opt = options_for_counts(options) select(opt[:select]).where(opt[:conditions]).joins(opt[:joins]).group(opt[:group]) end def options_for_counts(options = {}) options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :joins options = options.dup start_at = sanitize_sql(["#{Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at] end_at = sanitize_sql(["#{Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at] conditions = [ (sanitize_sql(options.delete(:conditions)) if options[:conditions]), start_at, end_at ].compact conditions = conditions.join(' AND ') if conditions.any? joins = ["INNER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"] joins << options.delete(:joins) if options[:joins] at_least = sanitize_sql(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least] at_most = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most] having = 'COUNT(*) > 0' having = [having, at_least, at_most].compact.join(' AND ') group_by = "#{Tag.table_name}.id, #{Tag.table_name}.name" # group_by << " AND #{having}" unless having.blank? { :select => "#{Tag.table_name}.id, #{Tag.table_name}.name, COUNT(*) AS count", :joins => joins.join(" "), :conditions => conditions, :group => group_by, :having => having }.update(options) end end end end end