Skip to content

Commit

Permalink
Create the association scope directly rather than going through with_…
Browse files Browse the repository at this point in the history
…scope
  • Loading branch information
jonleighton authored and tenderlove committed Jan 4, 2011
1 parent 1313d38 commit 99a8d84
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 31 deletions.
Expand Up @@ -333,7 +333,7 @@ def proxy_respond_to?(method, include_private = false)

protected

def construct_find_scope
def finder_options
{
:conditions => construct_conditions,
:select => construct_select,
Expand Down
36 changes: 20 additions & 16 deletions activerecord/lib/active_record/associations/association_proxy.rb
Expand Up @@ -169,7 +169,9 @@ def send(method, *args)
end

def scoped
with_scope(@scope) { target_klass.scoped }
target_scope.
apply_finder_options(@finder_options).
create_with(@creation_attributes)
end

protected
Expand All @@ -182,30 +184,26 @@ def sanitize_sql(sql, table_name = @reflection.klass.table_name)
@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

Expand All @@ -226,6 +224,12 @@ def target_klass
@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)
Expand Down Expand Up @@ -256,7 +260,7 @@ def method_missing(method, *args)
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

Expand Down
Expand Up @@ -60,7 +60,7 @@ def find_target
end
end

def construct_find_scope
def finder_options
{
:conditions => construct_conditions,
:select => @reflection.options[:select],
Expand Down
Expand Up @@ -79,7 +79,7 @@ def construct_owner_conditions
super(join_table)
end

def construct_find_scope
def finder_options
super.merge(
:joins => construct_joins,
:readonly => ambiguous_select?(@reflection.options[:select]),
Expand Down
Expand Up @@ -69,7 +69,7 @@ def delete_records(records)
end
end

def construct_create_scope
def creation_attributes
construct_owner_attributes
end
end
Expand Down
Expand Up @@ -68,7 +68,7 @@ def find_target
scoped.first.tap { |record| set_inverse_instance(record) }
end

def construct_find_scope
def finder_options
{
:conditions => construct_conditions,
:select => @reflection.options[:select],
Expand All @@ -78,7 +78,7 @@ def construct_find_scope
}
end

def construct_create_scope
def creation_attributes
construct_owner_attributes
end

Expand Down
Expand Up @@ -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] ||
Expand All @@ -24,7 +21,7 @@ def construct_find_scope
# 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

Expand Down

0 comments on commit 99a8d84

Please sign in to comment.