Skip to content

Commit

Permalink
Merge pull request mbleigh#359 from zquestz/master
Browse files Browse the repository at this point in the history
Refactored to go back to sub selects
  • Loading branch information
tilsammans committed May 15, 2013
2 parents be53d51 + 4aebba7 commit 2f2768f
Showing 1 changed file with 28 additions and 29 deletions.
57 changes: 28 additions & 29 deletions lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand All @@ -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
Expand Down Expand Up @@ -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.
#
Expand All @@ -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,
Expand All @@ -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) }
Expand All @@ -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))
Expand Down

0 comments on commit 2f2768f

Please sign in to comment.