From 4fbbd9c31338891dcd2abf23076651a0f3682876 Mon Sep 17 00:00:00 2001 From: Adam Milligan Date: Sat, 20 Sep 2008 13:58:59 -0700 Subject: [PATCH] Failing test case for belongs to proxy --- .../associations/belongs_to_associations_test.rb | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 37b6836..740b960 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -441,4 +441,15 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert log.valid? assert log.save end + + class ::Firm < Company + private + def private_method + "I'm private" + end + end + + def test_belongs_to_proxy_should_not_respond_to_private_methods + assert_raises(NoMethodError) { companies(:second_client).firm.private_method } + end end -- 1.6.0 From 7010f6df2d2379de0a21ccc093d6f8758b45e6ae Mon Sep 17 00:00:00 2001 From: Adam Milligan Date: Sat, 20 Sep 2008 14:36:27 -0700 Subject: [PATCH] Test cases for has_one and has_one_through --- .../associations/belongs_to_associations_test.rb | 3 ++- .../associations/has_one_associations_test.rb | 11 +++++++++++ .../has_one_through_associations_test.rb | 12 ++++++++++++ 3 files changed, 25 insertions(+), 1 deletions(-) diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 740b960..7c49013 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -442,7 +442,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert log.save end - class ::Firm < Company + class ::Firm private def private_method "I'm private" @@ -450,6 +450,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase end def test_belongs_to_proxy_should_not_respond_to_private_methods + assert_raises(NoMethodError) { companies(:first_firm).private_method } assert_raises(NoMethodError) { companies(:second_client).firm.private_method } end end diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index ec06be5..5da7815 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -349,4 +349,15 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert companies(:first_firm).readonly_account.readonly? end + class ::Account + private + def private_method + "I'm private" + end + end + + def test_has_one_proxy_should_not_respond_to_private_methods + assert_raises(NoMethodError) { accounts(:signals37).private_method } + assert_raises(NoMethodError) { companies(:first_firm).account.private_method } + end end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 77e3cb1..ccd4195 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -110,4 +110,16 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase new_member.club = new_club = Club.create(:name => "LRUG") assert_equal new_club, new_member.club.target end + + class ::Club + private + def private_method + "I'm private" + end + end + + def test_has_one_through_proxy_should_not_respond_to_private_methods + assert_raises(NoMethodError) { clubs(:moustache_club).private_method } + assert_raises(NoMethodError) { @member.club.private_method } + end end -- 1.6.0 From ec297c586d5288bfd19a98da794af25d2831eaf1 Mon Sep 17 00:00:00 2001 From: Adam Milligan Date: Sat, 20 Sep 2008 16:45:08 -0700 Subject: [PATCH] Association proxies no longer respond to private methods, unless called via send. --- .../associations/association_proxy.rb | 17 +++++++++++++++++ .../associations/has_one_association.rb | 2 +- .../associations/belongs_to_associations_test.rb | 5 +++++ .../associations/has_one_associations_test.rb | 5 +++++ .../has_one_through_associations_test.rb | 5 +++++ 5 files changed, 33 insertions(+), 1 deletions(-) diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index acdcd14..ab6bed5 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -193,10 +193,21 @@ module ActiveRecord @reflection.klass.send :with_scope, *args, &block end + def send_with_privacy_leniency(method, *args) + if loaded? && !self.respond_to?(method.to_s) && @target.private_methods.include?(method.to_s) + @target.send(method, *args) + else + send_without_privacy_leniency(method, *args) + end + end + alias_method_chain :send, :privacy_leniency + private # Forwards any missing method call to the \target. def method_missing(method, *args) if load_target + protect_if_private(method, args) + if block_given? @target.send(method, *args) { |*block_args| yield(*block_args) } else @@ -204,6 +215,12 @@ module ActiveRecord end end end + + def protect_if_private(method, args) + if @target.private_methods.include?(method.to_s) + raise NoMethodError.new("Attempt to call private method", method, args) + end + end # Loads the \target if needed and returns it. # diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index c92ef5c..9603230 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -57,7 +57,7 @@ module ActiveRecord protected def owner_quoted_id if @reflection.options[:primary_key] - quote_value(@owner.send(@reflection.options[:primary_key])) + @owner.class.quote_value(@owner.send(@reflection.options[:primary_key])) else @owner.quoted_id end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 7c49013..cd0ca5f 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -453,4 +453,9 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_raises(NoMethodError) { companies(:first_firm).private_method } assert_raises(NoMethodError) { companies(:second_client).firm.private_method } end + + def test_belongs_to_proxy_should_respond_to_private_methods_via_send + companies(:first_firm).send(:private_method) + companies(:second_client).firm.send(:private_method) + end end diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 5da7815..fd87602 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -360,4 +360,9 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_raises(NoMethodError) { accounts(:signals37).private_method } assert_raises(NoMethodError) { companies(:first_firm).account.private_method } end + + def test_has_one_proxy_should_respond_to_private_methods_via_send + accounts(:signals37).send(:private_method) + companies(:first_firm).account.send(:private_method) + end end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index ccd4195..e3739d7 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -122,4 +122,9 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase assert_raises(NoMethodError) { clubs(:moustache_club).private_method } assert_raises(NoMethodError) { @member.club.private_method } end + + def test_has_one_through_proxy_should_respond_to_private_methods_via_send + clubs(:moustache_club).send(:private_method) + @member.club.send(:private_method) + end end -- 1.6.0