remove N+1 queries in contributions#index

This commit is contained in:
Emi Matchu 2013-01-25 15:23:48 -06:00
parent a477bdc447
commit 8bb553701a
2 changed files with 15 additions and 11 deletions

View file

@ -7,6 +7,13 @@ class ContributionsController < ApplicationController
@contributions = Contribution.includes(:user)
end
@contributions = @contributions.recent.paginate :page => params[:page]
Contribution.preload_contributeds_and_parents @contributions
Contribution.preload_contributeds_and_parents(
@contributions,
:scopes => {
'Item' => Item.includes(:translations),
'PetType' => PetType.includes({:species => :translations,
:color => :translations})
}
)
end
end

View file

@ -26,12 +26,9 @@ class Contribution < ActiveRecord::Base
}
CONTRIBUTED_CHILDREN = CONTRIBUTED_RELATIONSHIPS.keys
CONTRIBUTED_TYPES = CONTRIBUTED_CHILDREN + CONTRIBUTED_RELATIONSHIPS.values
CONTRIBUTED_BASES = {}
CONTRIBUTED_TYPES.each do |type|
base = type == 'SwfAsset' ? SwfAsset.object_assets : type.constantize
CONTRIBUTED_BASES[type] = base
end
def self.preload_contributeds_and_parents(contributions)
def self.preload_contributeds_and_parents(contributions, options={})
options[:scopes] ||= {}
# Initialize the groups we'll be using for quick access
contributions_by_type = {}
contributed_by_type = {}
@ -56,8 +53,8 @@ class Contribution < ActiveRecord::Base
# Load contributed objects without parents, prepare them for easy access
# for future assignment to contributions and looking up parents
CONTRIBUTED_CHILDREN.each do |type|
base = CONTRIBUTED_BASES[type]
base.find(needed_ids_by_type[type]).each do |contributed|
scope = options[:scopes][type] || type.constantize.scoped
scope.find(needed_ids_by_type[type]).each do |contributed|
contributed_by_type[type] << contributed
contributed_by_type_and_id[type][contributed.id] = contributed
end
@ -67,10 +64,10 @@ class Contribution < ActiveRecord::Base
# contributed objects of that class. all_by_ids_or_children properly
# assigns parents to children, as well
CONTRIBUTED_RELATIONSHIPS.each do |child_type, type|
base = CONTRIBUTED_BASES[type]
scope = options[:scopes][type] || type.constantize.scoped
ids = needed_ids_by_type[type]
children = contributed_by_type[child_type]
base.all_by_ids_or_children(ids, children).each do |contributed|
scope.all_by_ids_or_children(ids, children).each do |contributed|
contributed_by_type_and_id[type][contributed.id] = contributed
end
end