From 05f1a9bcc3c9223768187e2379b508638dfa19b6 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 27 Jul 2011 12:36:00 +0100 Subject: Add a proxy_association method to association proxies, which can be called by association extensions to access information about the association. This replaces proxy_owner etc with proxy_association.owner. --- activerecord/CHANGELOG | 6 ++++++ activerecord/lib/active_record/associations.rb | 6 ++++++ .../lib/active_record/associations/collection_proxy.rb | 16 ++++++++++------ activerecord/test/cases/associations_test.rb | 5 +++++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index e448609cf4..e8d4b9c04e 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -24,6 +24,12 @@ a URI that specifies the connection configuration. For example: *Rails 3.1.0 (unreleased)* +* Add a proxy_association method to association proxies, which can be called by association + extensions to access information about the association. This replaces proxy_owner etc with + proxy_association.owner. + + [Jon Leighton] + * ActiveRecord::MacroReflection::AssociationReflection#build_record has a new method signature. Before: def build_association(*options) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 029d7a9b15..2605a54cb6 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -460,6 +460,12 @@ module ActiveRecord # * record.association(:items).target - Returns the associated object for +belongs_to+ and +has_one+, or # the collection of associated objects for +has_many+ and +has_and_belongs_to_many+. # + # However, inside the actual extension code, you will not have access to the record as + # above. In this case, you can access proxy_association. For example, + # record.association(:items) and record.items.proxy_association will return + # the same object, allowing you to make calls like proxy_association.owner inside + # association extensions. + # # === Association Join Models # # Has Many associations can be configured with the :through option to use an diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 827dfb7ccb..6ba3d45aff 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -58,23 +58,27 @@ module ActiveRecord alias_method :new, :build + def proxy_association + @association + end + def respond_to?(name, include_private = false) super || (load_target && target.respond_to?(name, include_private)) || - @association.klass.respond_to?(name, include_private) + proxy_association.klass.respond_to?(name, include_private) end def method_missing(method, *args, &block) match = DynamicFinderMatch.match(method) if match && match.instantiator? send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r| - @association.send :set_owner_attributes, r - @association.send :add_to_target, r + proxy_association.send :set_owner_attributes, r + proxy_association.send :add_to_target, r yield(r) if block_given? end end - if target.respond_to?(method) || (!@association.klass.respond_to?(method) && Class.respond_to?(method)) + if target.respond_to?(method) || (!proxy_association.klass.respond_to?(method) && Class.respond_to?(method)) if load_target if target.respond_to?(method) target.send(method, *args, &block) @@ -104,7 +108,7 @@ module ActiveRecord alias_method :to_a, :to_ary def <<(*records) - @association.concat(records) && self + proxy_association.concat(records) && self end alias_method :push, :<< @@ -114,7 +118,7 @@ module ActiveRecord end def reload - @association.reload + proxy_association.reload self end end diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb index 49d82ba2df..ffe2993e0f 100644 --- a/activerecord/test/cases/associations_test.rb +++ b/activerecord/test/cases/associations_test.rb @@ -203,6 +203,11 @@ class AssociationProxyTest < ActiveRecord::TestCase assert_equal david.projects, david.projects.reload.reload end end + + def test_proxy_association_accessor + david = developers(:david) + assert_equal david.association(:projects), david.projects.proxy_association + end end class OverridingAssociationsTest < ActiveRecord::TestCase -- cgit v1.2.3