This project is archived and is in readonly mode.
has_many :through should work if the join model uses has_one relationship
Reported by sbwoodside | May 26th, 2009 @ 05:07 AM
Let's say you have User has_many Posts, and each Post has_one Photo. If you try to set a has_many :photos, :through :posts and then access user.photos you will get something like this:
ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection macro :has_one for has_many :photos, :through => :posts. Use :source to specify the source reflection.
Besides the fact that the error message isn't too helpful, it appears that this isn't supported in Rails 2.3.2 or previously. It would be awfully nice to be able to, for example, list all of the Photos for a certain User, etc.
There is an old bug in Rails Trac for this, which can no longer be modified.
It's not an uncommon problem: http://railsforum.com/viewtopic.php?pid=86321#p86321 and http://railsforum.com/viewtopic.php?id=2295 and http://railsforum.com/viewtopic.php?id=265#p4120 and http://railsforum.com/viewtopic.php?pid=6388#p6388
Is there a suggested workaround? (Aside from hacking SQL...)
Comments and changes to this ticket
-
CancelProfileIsBroken May 26th, 2009 @ 01:36 PM
- State changed from new to incomplete
This looks like a duplicate of #1149. Bottom line: hasn't ever worked, documented as not working on http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassM.... If you'd like to submit a patch and failing test case, I'm sure core team would consider.
Potential workaround: change to Post has_many :photos, though obviously that changes the semantics and you'd have to enforce uniqueness in other code.
-
sbwoodside June 8th, 2009 @ 03:21 AM
Is it not permissible to have a bug open on this as something to fix at some point? The workaround is not something I would like to do.
-
sbwoodside June 8th, 2009 @ 03:41 AM
Well, this seems to work as a hackish work-around and relatively efficient if most of your posts have a photo. I'm not really an SQL guru so if someone could post better SQL that would be nice :-)
@photos = @user.posts.map { |post| post.photo } .compact
-
Josh Sharpe July 11th, 2009 @ 11:22 PM
This patch seems to work for me, but I really don't know enough about the inner workings of associations to be sure.
-
CancelProfileIsBroken August 4th, 2009 @ 08:15 PM
- Tag changed from activerecord, association, associations, hasmanythroughsourceassociationmacroerror, has_many, has_one, through to activerecord, association, associations, bugmash, hasmanythroughsourceassociationmacroerror, has_many, has_one, through
- State changed from incomplete to open
-
Gabe da Silveira August 9th, 2009 @ 12:45 AM
verified that the patch applies to 2-3-stable and tests pass for mysql/sqlite/postgres. Going to look a little deeper now for potential problems...
-
Gabe da Silveira August 9th, 2009 @ 03:47 AM
After looking at this deeper the main problem is with inserting and deleting records via the has_many :through => has_one relationship. However the main use case of this association is read-only anyway, so I think there is good value here, and I believe Josh's patch works smoothly because of support for has_many :through has_many.
I believe the proper thing to do here is add an exception similar to HasManyThroughCantAssociateThroughHasManyReflection to make the read-only functionality explicit and update the documentation. I'm willing to do that now if there is agreement that this is the right approach.
-
Gabe da Silveira August 9th, 2009 @ 05:03 AM
- Tag changed from activerecord, association, associations, bugmash, hasmanythroughsourceassociationmacroerror, has_many, has_one, through to activerecord, association, associations, bugmash, hasmanythroughsourceassociationmacroerror, has_many, has_one, through, verified
Okay, I've attached a patch. This enabled has_many :through for use with a has_one reflection on the join model. It's enabled as read-only with the same mechanics as has_many :through has_many. I started with Josh's patch and added the read-only test + documentation updates.
-
Gabe da Silveira August 9th, 2009 @ 05:55 AM
Oops, I left an unused Exception in there. That is removed in this updated patch for 2-3-stable, and also I have a rebased version to apply to master.
I've attached a patch.
-
Gabe da Silveira August 9th, 2009 @ 11:29 AM
Per koz's request, here is an updated patch with an official deprection for the old exception for the 2-3 branch.
-
Josh Nichols August 9th, 2009 @ 08:31 PM
+1 for the functionality. I could use this behavior one of my current projects.
Unfortunately, I wasn't able to apply your last version of the patch against 2-3-stable or master.
-
Tristan Dunn August 9th, 2009 @ 08:33 PM
+1 Verified
Cleanly applies (apart from whitespace warning) and passes on master and 2-3-stable.
-
Tristan Dunn August 9th, 2009 @ 08:36 PM
Sorry, doesn't apply on the latest versions as Josh pointed out.
-
Gabe da Silveira August 9th, 2009 @ 08:57 PM
Here are updated patches for 2-3-stable and master. Handy-dandy one-stop location:
-
Gabe da Silveira August 9th, 2009 @ 09:00 PM
Crap. The deprecation snuck into master diff as well, which I don't think it should be according to my impression from koz. Without the deprecation:
-
Josh Nichols August 9th, 2009 @ 09:52 PM
Verified that the patch applies to 2-3-stable and master, and that the functionality works as expected through manual testing.
I ran these commands:
rails 2719-demo cd 2719-demo script/generate model user script/generate model post user_id:integer script/generate model photo post_id:integer rake db:create db:migrate
Then used these models:
class User < ActiveRecord::Base has_many :posts has_many :photos, :through => :posts end
class Post < ActiveRecord::Base belongs_to :user has_one :photo end
class Photo < ActiveRecord::Base belongs_to :post endAnd then played around in script/console:
>> user = User.create! => #<User id: 2, created_at: "2009-08-09 20:51:27", updated_at: "2009-08-09 20:51:27"> >> post = user.posts.create => #<Post id: 3, user_id: 2, created_at: "2009-08-09 20:51:34", updated_at: "2009-08-09 20:51:34"> >> post.create_photo => #<Photo id: 3, post_id: 3, created_at: "2009-08-09 20:51:37", updated_at: "2009-08-09 20:51:37"> >> user.photos => [#<Photo id: 3, post_id: 3, created_at: "2009-08-09 20:51:37", updated_at: "2009-08-09 20:51:37">]
-
Repository August 10th, 2009 @ 12:44 AM
- State changed from open to resolved
(from [00d6c766608f90ce64f11feb98786cbc7f71b89d]) Enable has_many :through for going through a has_one association on the join model [#2719 state:resolved]
Signed-off-by: Pratik Naik pratiknaik@gmail.com
http://github.com/rails/rails/commit/00d6c766608f90ce64f11feb98786c... -
Repository August 10th, 2009 @ 12:44 AM
(from [b763858ed5faeda720035dd2178e7c44aa34240a]) Enable has_many :through for going through a has_one association on the join model [#2719 state:resolved]
Signed-off-by: Pratik Naik pratiknaik@gmail.com
http://github.com/rails/rails/commit/b763858ed5faeda720035dd2178e7c... -
CancelProfileIsBroken August 10th, 2009 @ 02:15 AM
- Tag changed from activerecord, association, associations, bugmash, hasmanythroughsourceassociationmacroerror, has_many, has_one, through, verified to activerecord, association, associations, hasmanythroughsourceassociationmacroerror, has_many, has_one, through, verified
- Milestone cleared.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
Attachments
Tags
Referenced by
- 2719 has_many :through should work if the join model uses has_one relationship (from [00d6c766608f90ce64f11feb98786cbc7f71b89d]) Enable ...
- 2719 has_many :through should work if the join model uses has_one relationship (from [b763858ed5faeda720035dd2178e7c44aa34240a]) Enable ...