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)


124
125
126
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 124

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



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 132

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


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
202
203
204
205
206
207
208
209
210
211
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 176

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


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

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

#is_taggable?Boolean

Returns:

  • (Boolean)


213
214
215
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 213

def is_taggable?
  true
end

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



128
129
130
# File 'lib/acts_as_taggable_on/acts_as_taggable_on.rb', line 128

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