Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Provide Association Extensions access to the instance that the associ…

…ation is being accessed from. Closes #4433 [josh@hasmanythrough.com]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4372 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit ea51d72edb36737445834777f06664096066a0ba 1 parent 062845b
@technoweenie technoweenie authored
View
3  activerecord/CHANGELOG
@@ -1,5 +1,8 @@
*SVN*
+* Provide Association Extensions access to the instance that the association is being accessed from.
+ Closes #4433 [josh@hasmanythrough.com]
+
* Update OpenBase adaterp's maintainer's email address. Closes #5176. [Derrick Spell]
* Add a quick note about :select and eagerly included associations. [Rick]
View
7 activerecord/lib/active_record/associations.rb
@@ -232,6 +232,13 @@ def clear_association_cache #:nodoc:
# has_many :people, :extend => [FindOrCreateByNameExtension, FindRecentExtension]
# end
#
+ # Some extensions can only be made to work with knowledge of the association proxy's internals.
+ # Extensions can access relevant state using accessors on the association proxy:
+ #
+ # * +proxy_owner+ - Returns the object the association is part of.
+ # * +proxy_reflection+ - Returns the reflection object that describes the association.
+ # * +proxy_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.
+ #
# === Association Join Models
#
# Has Many associations can be configured with the :through option to use an explicit join model to retrieve the data. This
View
14 activerecord/lib/active_record/associations/association_proxy.rb
@@ -4,7 +4,7 @@ class AssociationProxy #:nodoc:
attr_reader :reflection
alias_method :proxy_respond_to?, :respond_to?
alias_method :proxy_extend, :extend
- instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ }
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_)/ }
def initialize(owner, reflection)
@owner, @reflection = owner, reflection
@@ -12,6 +12,18 @@ def initialize(owner, reflection)
reset
end
+ def proxy_owner
+ @owner
+ end
+
+ def proxy_reflection
+ @reflection
+ end
+
+ def proxy_target
+ @target
+ end
+
def respond_to?(symbol, include_priv = false)
proxy_respond_to?(symbol, include_priv) || (load_target && @target.respond_to?(symbol, include_priv))
end
View
23 activerecord/test/associations_test.rb
@@ -65,6 +65,29 @@ def test_storing_in_pstore
end
end
+class AssociationProxyTest < Test::Unit::TestCase
+ fixtures :authors, :posts
+
+ def test_proxy_accessors
+ welcome = posts(:welcome)
+ assert_equal welcome, welcome.author.proxy_owner
+ assert_equal welcome.class.reflect_on_association(:author), welcome.author.proxy_reflection
+ welcome.author.class # force load target
+ assert_equal welcome.author, welcome.author.proxy_target
+
+ david = authors(:david)
+ assert_equal david, david.posts.proxy_owner
+ assert_equal david.class.reflect_on_association(:posts), david.posts.proxy_reflection
+ david.posts.first # force load target
+ assert_equal david.posts, david.posts.proxy_target
+
+ assert_equal david, david.posts_with_extension.testing_proxy_owner
+ assert_equal david.class.reflect_on_association(:posts_with_extension), david.posts_with_extension.testing_proxy_reflection
+ david.posts_with_extension.first # force load target
+ assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
+ end
+end
+
class HasOneAssociationsTest < Test::Unit::TestCase
fixtures :accounts, :companies, :developers, :projects, :developers_projects
View
11 activerecord/test/fixtures/author.rb
@@ -3,6 +3,17 @@ class Author < ActiveRecord::Base
has_many :posts_with_comments, :include => :comments, :class_name => "Post"
has_many :posts_with_categories, :include => :categories, :class_name => "Post"
has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post"
+ has_many :posts_with_extension, :class_name => "Post" do #, :extend => ProxyTestExtension
+ def testing_proxy_owner
+ proxy_owner
+ end
+ def testing_proxy_reflection
+ proxy_reflection
+ end
+ def testing_proxy_target
+ proxy_target
+ end
+ end
has_many :comments, :through => :posts
has_many :funky_comments, :through => :posts, :source => :comments
Please sign in to comment.
Something went wrong with that request. Please try again.