forked from OpenNeo/impress
f997513e87
Ohh ok, without this change all of our `scope`s were just immediately evaluating the argument and fetching _all_ such matching records immediately, instead of waiting to actually be called. This led to bugs like `pet_type.as_json` returning ALL pet states in the whole db, because the `PetState.emotion_order` scope was being treated as a single predefined query, rather than a query fragment to merge into the current context.
This also explains what happened in 724ed83
: that's why things before the scope in the query were being ignored.
82 lines
2.8 KiB
Ruby
82 lines
2.8 KiB
Ruby
class Contribution < ActiveRecord::Base
|
|
POINT_VALUES = {
|
|
'Item' => 3,
|
|
'SwfAsset' => 2,
|
|
'PetType' => 15,
|
|
'PetState' => 10
|
|
}
|
|
|
|
belongs_to :contributed, :polymorphic => true
|
|
belongs_to :user
|
|
|
|
scope :recent, -> { order('id DESC') }
|
|
|
|
cattr_reader :per_page
|
|
@@per_page = 30
|
|
|
|
def point_value
|
|
POINT_VALUES[contributed_type] ||
|
|
raise("unexpected contributed type #{contributed_type.inspect} for " +
|
|
"contributed #{contributed.inspect}")
|
|
end
|
|
|
|
CONTRIBUTED_RELATIONSHIPS = {
|
|
'SwfAsset' => 'Item',
|
|
'PetState' => 'PetType'
|
|
}
|
|
CONTRIBUTED_CHILDREN = CONTRIBUTED_RELATIONSHIPS.keys
|
|
CONTRIBUTED_TYPES = CONTRIBUTED_CHILDREN + CONTRIBUTED_RELATIONSHIPS.values
|
|
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 = {}
|
|
contributed_by_type_and_id = {}
|
|
needed_ids_by_type = {}
|
|
CONTRIBUTED_TYPES.each do |type|
|
|
contributions_by_type[type] = []
|
|
contributed_by_type[type] = []
|
|
contributed_by_type_and_id[type] = {}
|
|
needed_ids_by_type[type] = []
|
|
end
|
|
|
|
# Go through the contributions to sort them for future contributed
|
|
# assignment, and so we can know what immediate contributed items we'll
|
|
# need to look up
|
|
contributions.each do |contribution|
|
|
type = contribution.contributed_type
|
|
contributions_by_type[type] << contribution
|
|
needed_ids_by_type[type] << contribution.contributed_id
|
|
end
|
|
|
|
# Load contributed objects without parents, prepare them for easy access
|
|
# for future assignment to contributions and looking up parents
|
|
CONTRIBUTED_CHILDREN.each do |type|
|
|
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
|
|
end
|
|
|
|
# Load both parents of the children we just got, and immediately
|
|
# contributed objects of that class. all_by_ids_or_children properly
|
|
# assigns parents to children, as well
|
|
CONTRIBUTED_RELATIONSHIPS.each do |child_type, type|
|
|
scope = options[:scopes][type] || type.constantize.scoped
|
|
ids = needed_ids_by_type[type]
|
|
children = contributed_by_type[child_type]
|
|
scope.all_by_ids_or_children(ids, children).each do |contributed|
|
|
contributed_by_type_and_id[type][contributed.id] = contributed
|
|
end
|
|
end
|
|
|
|
# Assign contributed objects to contributions
|
|
contributions.each do |contribution|
|
|
type = contribution.contributed_type
|
|
id = contribution.contributed_id
|
|
contribution.contributed = contributed_by_type_and_id[type][id]
|
|
end
|
|
end
|
|
end
|