Module: ActiveRecord::Acts::TaggableOn::SingletonMethods

Defined in:
lib/acts_as_taggable_on/acts_as_taggable_on.rb

Instance Method Summary collapse

Instance Method Details

#caching_tag_list_on?(context) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 114

def caching_tag_list_on?(context)
  column_names.include?("cached_#{context.to_s.singularize}_list")
end

#find_options_for_find_tagged_with(tags, options = {}) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 122

def find_options_for_find_tagged_with(tags, options = {})
  tags = tags.is_a?(Array) ? TagList.new(tags.map(&:to_s)) : TagList.from(tags)

  return {} if tags.empty?

  conditions = []
  conditions << sanitize_sql(options.delete(:conditions)) if options[:conditions]
  
  unless (on = options.delete(:on)).nil?
    conditions << sanitize_sql(["context = ?",on.to_s])
  end

  taggings_alias, tags_alias = "#{table_name}_taggings", "#{table_name}_tags"

  if options.delete(:exclude)
    tags_conditions = tags.map { |t| sanitize_sql(["#{Tag.table_name}.name LIKE ?", t]) }.join(" OR ")
    conditions << sanitize_sql(["#{table_name}.id NOT IN (SELECT #{Tagging.table_name}.taggable_id FROM #{Tagging.table_name} LEFT OUTER JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id WHERE (#{tags_conditions}) AND #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)})", tags])
  else
    conditions << tags.map { |t| sanitize_sql(["#{tags_alias}.name LIKE ?", t]) }.join(" OR ")

    if options.delete(:match_all)
      group = "#{taggings_alias}.taggable_id HAVING COUNT(#{taggings_alias}.taggable_id) = #{tags.size}"
    end
  end
  
  { :select => "DISTINCT #{table_name}.*",
    :joins => "LEFT OUTER JOIN #{Tagging.table_name} #{taggings_alias} ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key} AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)} " +
              "LEFT OUTER JOIN #{Tag.table_name} #{tags_alias} ON #{tags_alias}.id = #{taggings_alias}.tag_id",
    :conditions => conditions.join(" AND "),
    :group      => group
  }.update(options)
end

#find_options_for_tag_counts(options = {}) ⇒ Object

Calculate the tag counts for all tags.

Options:

: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 'tags.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
:on - Scope the find to only include a certain context


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 166

def find_options_for_tag_counts(options = {})
  options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :on
  
  scope = scope(:find)
  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]

  type_and_context = "#{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)}"
  
  conditions = [
    type_and_context,
    options[:conditions],
    start_at,
    end_at
  ]

  conditions = conditions.compact.join(' AND ')
  conditions = merge_conditions(conditions, scope[:conditions]) if scope

  joins = ["LEFT OUTER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"]
  joins << sanitize_sql(["AND #{Tagging.table_name}.context = ?",options.delete(:on).to_s]) unless options[:on].nil?
  joins << "LEFT OUTER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{Tagging.table_name}.taggable_id"
  joins << scope[:joins] if scope && scope[: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    = [at_least, at_most].compact.join(' AND ')
  group_by  = "#{Tag.table_name}.id, #{Tag.table_name}.name HAVING COUNT(*) > 0"
  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
  }.update(options)
end

#find_tagged_with(*args) ⇒ Object

Pass either a tag string, or an array of strings or tags

Options:

:exclude - Find models that are not tagged with the given tags
:match_all - Find models that match all of the given tags, not just one
:conditions - A piece of SQL conditions to add to the query
:on - scopes the find to a context


109
110
111
112
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 109

def find_tagged_with(*args)
  options = find_options_for_find_tagged_with(*args)
  options.blank? ? [] : find(:all,options)
end

#is_taggable?Boolean

Returns:

  • (Boolean)


203
204
205
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 203

def is_taggable?
  true
end

#tag_counts_on(context, options = {}) ⇒ Object



118
119
120
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 118

def tag_counts_on(context, options = {})
  Tag.find(:all, find_options_for_tag_counts(options.merge({:on => context.to_s})))
end