Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

PIVOTAL LABS
Standup 11/18/2008: Unbelievable has_many :through Gotcha
  • 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_photos
    
    • a_user.photos.create will create and persist both a Photo object and the UserPhoto join object
    • photo = a_user.photos.build followed by photo.save will create and persist the Photo object only, and will not persist an appropriate UserPhoto join object.
  • Rails 2.2: Test::Unit::TestCase extentions have been removed from Rails Core and are now in ActiveSupport::TestCase. As stated in the Groups Thread about this, use ActiveSupport::TestCase instead of Test::Unit::TestCase in test/test_helper.rb.

Comments
  1. Mark Wilden says:

    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.

  2. stefano says:

    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.

  3. Josh Susser says:

    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.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *