From 9c1ca232ea37528447538f8be2157b3a209c432f Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 19 Dec 2010 14:17:29 +0000 Subject: [PATCH] Don't allow a has_one association to go :through a collection association [#2976 state:resolved] --- activerecord/lib/active_record/associations.rb | 6 ++++++ activerecord/lib/active_record/reflection.rb | 4 ++++ .../has_one_through_associations_test.rb | 12 +++++++----- activerecord/test/models/author.rb | 4 +++- activerecord/test/models/member.rb | 9 ++++++--- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index cdc8f25..c0cd222 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -32,6 +32,12 @@ module ActiveRecord end end + class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc: + def initialize(owner_class_name, reflection, through_reflection) + super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.") + end + end + class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc: def initialize(reflection) through_reflection = reflection.through_reflection diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index b9caa64..b49a761 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -384,6 +384,10 @@ module ActiveRecord raise HasManyThroughSourceAssociationMacroError.new(self) end + if macro == :has_one && through_reflection.collection? + raise HasOneThroughCantAssociateThroughCollection.new(active_record.name, self, through_reflection) + end + check_validity_of_inverse! 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 93a4f49..d57c7e8 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -25,10 +25,6 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase assert_equal clubs(:boring_club), @member.club end - def test_has_one_through_with_has_many - assert_equal clubs(:moustache_club), @member.favourite_club - end - def test_creating_association_creates_through_record new_member = Member.create(:name => "Chris") new_member.club = Club.create(:name => "LRUG") @@ -235,6 +231,12 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase end def test_has_one_through_with_default_scope_on_join_model - assert_equal posts(:welcome).comments.first, authors(:david).comment_on_first_posts + assert_equal posts(:welcome).comments.first, authors(:david).comment_on_first_post + end + + def test_has_one_through_many_raises_exception + assert_raise(ActiveRecord::HasOneThroughCantAssociateThroughCollection) do + members(:groucho).club_through_many + end end end diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb index fd6d2b3..244c5ac 100644 --- a/activerecord/test/models/author.rb +++ b/activerecord/test/models/author.rb @@ -28,7 +28,9 @@ class Author < ActiveRecord::Base has_many :first_posts has_many :comments_on_first_posts, :through => :first_posts, :source => :comments, :order => 'posts.id desc, comments.id asc' - has_one :comment_on_first_posts, :through => :first_posts, :source => :comments, :order => 'posts.id desc, comments.id asc' + + has_one :first_post + has_one :comment_on_first_post, :through => :first_post, :source => :comments, :order => 'posts.id desc, comments.id asc' has_many :thinking_posts, :class_name => 'Post', :conditions => { :title => 'So I was thinking' }, :dependent => :delete_all has_many :welcome_posts, :class_name => 'Post', :conditions => { :title => 'Welcome to the weblog' } diff --git a/activerecord/test/models/member.rb b/activerecord/test/models/member.rb index 255fb56..5b0a5eb 100644 --- a/activerecord/test/models/member.rb +++ b/activerecord/test/models/member.rb @@ -1,12 +1,15 @@ class Member < ActiveRecord::Base has_one :current_membership - has_many :memberships + has_one :membership has_many :fellow_members, :through => :club, :source => :members has_one :club, :through => :current_membership - has_one :favourite_club, :through => :memberships, :conditions => ["memberships.favourite = ?", true], :source => :club + has_one :favourite_club, :through => :membership, :conditions => ["memberships.favourite = ?", true], :source => :club has_one :sponsor, :as => :sponsorable has_one :sponsor_club, :through => :sponsor has_one :member_detail has_one :organization, :through => :member_detail belongs_to :member_type -end \ No newline at end of file + + has_many :current_memberships + has_one :club_through_many, :through => :current_memberships, :source => :club +end -- 1.7.1