diff --git a/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb b/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb index 9cba53a17..60eb4bd6e 100644 --- a/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +++ b/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb @@ -5,7 +5,7 @@ def self.included(base) base.extend ActsAsTaggableOn::Taggable::Collection::ClassMethods base.initialize_acts_as_taggable_on_collection end - + module ClassMethods def initialize_acts_as_taggable_on_collection tag_types.map(&:to_s).each do |tag_type| @@ -24,16 +24,16 @@ def top_#{tag_type}(limit = 10) def self.top_#{tag_type}(limit = 10) tag_counts_on('#{tag_type}', :order => 'count desc', :limit => limit.to_i) - end + end RUBY - end + end end - + def acts_as_taggable_on(*args) super(*args) initialize_acts_as_taggable_on_collection end - + def tag_counts_on(context, options = {}) all_tag_counts(options.merge({:on => context.to_s})) end @@ -86,12 +86,13 @@ def all_tags(options = {}) group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id" # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore: - ids = select("#{table_name}.#{primary_key}").map(&:id) - tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(?)", ids).group(group_columns) - - tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id") + scoped_select = "#{table_name}.#{primary_key}" + tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})").group(group_columns) + + tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id") + tag_scope end - + ## # Calculate the tag counts for all tags. # @@ -110,29 +111,29 @@ def all_tag_counts(options = {}) scope = {} ## Generate conditions: - options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions] + options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions] start_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at] end_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at] - + taggable_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.taggable_type = ?", base_class.name]) - taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options.delete(:id)]) if options[:id] + taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options[:id]]) if options[:id] taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", options.delete(:on).to_s]) if options[:on] - + tagging_conditions = [ taggable_conditions, scope[:conditions], start_at_conditions, end_at_conditions ].compact.reverse - + tag_conditions = [ - options[:conditions] + options[:conditions] ].compact.reverse - + ## Generate joins: taggable_join = "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id" - taggable_join << " AND #{table_name}.#{inheritance_column} = '#{name}'" unless descends_from_active_record? # Current model is STI descendant, so add type checking to the join condition + taggable_join << " AND #{table_name}.#{inheritance_column} = '#{name}'" unless descends_from_active_record? # Current model is STI descendant, so add type checking to the join condition tagging_joins = [ taggable_join, @@ -144,10 +145,10 @@ def all_tag_counts(options = {}) ## Generate scope: tagging_scope = ActsAsTaggableOn::Tagging.select("#{ActsAsTaggableOn::Tagging.table_name}.tag_id, COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) AS tags_count") - tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit]) + tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit]) # Joins and conditions - tagging_joins.each { |join| tagging_scope = tagging_scope.joins(join) } + tagging_joins.each { |join| tagging_scope = tagging_scope.joins(join) } tagging_conditions.each { |condition| tagging_scope = tagging_scope.where(condition) } tag_joins.each { |join| tag_scope = tag_scope.joins(join) } @@ -156,25 +157,23 @@ def all_tag_counts(options = {}) # GROUP BY and HAVING clauses: at_least = sanitize_sql(["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) >= ?", options.delete(:at_least)]) if options[:at_least] at_most = sanitize_sql(["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) <= ?", options.delete(:at_most)]) if options[:at_most] - having = ["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) > 0", at_least, at_most].compact.join(' AND ') + having = ["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) > 0", at_least, at_most].compact.join(' AND ') group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id" - # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore: - scoped_select = "#{table_name}.#{primary_key}" - select_query = "#{select(scoped_select).to_sql}" + unless options[:id] + # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore: + scoped_select = "#{table_name}.#{primary_key}" + tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})") + end - res = ActiveRecord::Base.connection.select_all(select_query).map { |item| item.values }.flatten.compact.join(",") - res = "NULL" if res.blank? - - tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{res})") tagging_scope = tagging_scope.group(group_columns).having(having) tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id") tag_scope end end - + module InstanceMethods def tag_counts_on(context, options={}) self.class.tag_counts_on(context, options.merge(:id => id))