Create the association scope directly rather than going through with_scope

This commit is contained in:
Jon Leighton
2011-01-03 12:04:33 +00:00
committed by Aaron Patterson
parent 1313d386da
commit 99a8d8430f
7 changed files with 32 additions and 31 deletions

View File

@@ -333,7 +333,7 @@ module ActiveRecord
protected
def construct_find_scope
def finder_options
{
:conditions => construct_conditions,
:select => construct_select,

View File

@@ -169,7 +169,9 @@ module ActiveRecord
end
def scoped
with_scope(@scope) { target_klass.scoped }
target_scope.
apply_finder_options(@finder_options).
create_with(@creation_attributes)
end
protected
@@ -182,30 +184,26 @@ module ActiveRecord
@reflection.klass.send(:sanitize_sql, sql, table_name)
end
# Forwards +with_scope+ to the reflection.
def with_scope(*args, &block)
target_klass.send :with_scope, *args, &block
end
# Construct the scope used for find/create queries on the target
# Construct the data used for the scope for this association
#
# Note that we don't actually build the scope here, we just construct the options and
# attributes. We must only build the scope when it's actually needed, because at that
# point the call may be surrounded by scope.scoping { ... } or with_scope { ... } etc,
# which affects the scope which actually gets built.
def construct_scope
if target_klass
@scope = {
:find => construct_find_scope,
:create => construct_create_scope
}
else
@scope = nil
@finder_options = finder_options
@creation_attributes = creation_attributes
end
end
# Implemented by subclasses
def construct_find_scope
def finder_options
raise NotImplementedError
end
# Implemented by (some) subclasses
def construct_create_scope
def creation_attributes
{}
end
@@ -226,6 +224,12 @@ module ActiveRecord
@reflection.klass
end
# Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
# through association's scope)
def target_scope
target_klass.scoped
end
private
# Forwards any missing method call to the \target.
def method_missing(method, *args)
@@ -256,7 +260,7 @@ module ActiveRecord
def load_target
return nil unless defined?(@loaded)
if !loaded? && (!@owner.new_record? || foreign_key_present?) && @scope
if !loaded? && (!@owner.new_record? || foreign_key_present?) && target_klass
@target = find_target
end

View File

@@ -60,7 +60,7 @@ module ActiveRecord
end
end
def construct_find_scope
def finder_options
{
:conditions => construct_conditions,
:select => @reflection.options[:select],

View File

@@ -79,7 +79,7 @@ module ActiveRecord
super(join_table)
end
def construct_find_scope
def finder_options
super.merge(
:joins => construct_joins,
:readonly => ambiguous_select?(@reflection.options[:select]),

View File

@@ -69,7 +69,7 @@ module ActiveRecord
end
end
def construct_create_scope
def creation_attributes
construct_owner_attributes
end
end

View File

@@ -68,7 +68,7 @@ module ActiveRecord
scoped.first.tap { |record| set_inverse_instance(record) }
end
def construct_find_scope
def finder_options
{
:conditions => construct_conditions,
:select => @reflection.options[:select],
@@ -78,7 +78,7 @@ module ActiveRecord
}
end
def construct_create_scope
def creation_attributes
construct_owner_attributes
end

View File

@@ -3,16 +3,13 @@ module ActiveRecord
module Associations
module ThroughAssociation
def scoped
with_scope(@scope) do
@reflection.klass.scoped &
@reflection.through_reflection.klass.scoped
end
end
protected
def construct_find_scope
def target_scope
super & @reflection.through_reflection.klass.scoped
end
def finder_options
super.merge(
:joins => construct_joins,
:include => @reflection.options[:include] ||
@@ -24,7 +21,7 @@ module ActiveRecord
# moment we only support creating on a :through association when the source reflection is a
# belongs_to. Thus it's not necessary to set a foreign key on the associated record(s), so
# this scope has can legitimately be empty.
def construct_create_scope
def creation_attributes
{ }
end