One team discovered a jaw-dropping issue with has_many :through. Given the following:
class User < ActiveRecord::Base has_many :user_photos has_many :photos, :through => :user_photosa_user.photos.createwill create and persist both a Photo object and the UserPhoto join objectphoto = a_user.photos.buildfollowed byphoto.savewill create and persist the Photo object only, and will not persist an appropriate UserPhoto join object.
Rails 2.2:
Test::Unit::TestCaseextentions have been removed from Rails Core and are now inActiveSupport::TestCase. As stated in the Groups Thread about this, useActiveSupport::TestCaseinstead ofTest::Unit::TestCasein test/test_helper.rb.
Standup 11/18/2008: Unbelievable has_many :through Gotcha
Tuesday, November 18, 2008
I don’t see how photo.save could know anything about UserPhoto.
That said, some of my most initially frustrating moments with Rails came when trying to create associations: e.g., adding a has_many object when the owner hasn’t been saved yet.
November 19, 2008 at 1:04 am
I may be wrong, but I don’t think you’re supposed to create objects via a has_many_through association. For me, it’s just a convenient way to express a join. I remember that when we defined “flattened relationships” in WebObjects (same concept) they were invariably read-only.
November 19, 2008 at 8:44 am
Stefano, you can indeed create join model object via a has_many :through association. But there are limitations.
One of the quirks of hmt is that you need to have both endpoint objects saved to be able to create the join model object, so that it has both foreign keys / ids to work with. The hmt #create method can create the join model since it’s creating the endpoint object. But #build explicitly doesn’t save the endpoint, meaning no id, so there’s no way to create the join model. Yes, this seems broken, or at least confusing. There’s probably a way to fix it, but it would require some thought about what the right thing to do is.
November 19, 2008 at 1:23 pm