Feb 17 2010
∞
has_many :through, accepts_nested_attributes_for, and validations
I had a need to write some code that would permit the following:
it "accepts attributes for item_photos" do
photo = Factory(:photo)
item = Item.create!(Factory.attributes_for(:item, :item_photos_attributes => [{:photo_id => photo.id}]))
item.item_photos.should have(1).item_photo
item.photos.first.should == photo
end
Basically, you can use nested attributes to when creating items to create lookup records for existing photos.
Of course, the create kept failing due to the item_photo in question missing an item (well, actually … I started with a create, which of course happily continued on its way until I tried to look at item photos and it was blank. The lesson is that you should ALWAYS test that your create or saves have occured, either with a should be_true or a bang method so they explode).
This blew my mind — how does accept_nested_attributes_for even work if you need to have an id before saving child associations? Well, it was my fault, of course. My item_photos model looked like this:
class ItemPhoto < ActiveRecord::Base belongs_to :item belongs_to :photo validates_presence_of :item validates_presence_of :photo endI added the validations because I believed it would be silly to have an item_photo without an associated item or photo. What would you do with such a thing? Of course, my overzealous validating meant my accept_nested_attributes could never hope to succeed. Removing these validations made the test pass happily. Basically, this seems to indicate that Rails can’t yet handle validations on parent belongs_to associations in children yet, so you’re probably going to have to skip them. It sounds like this is possibly going to make it into a future version of rails, but if not, there you have it: a simple solution for a foolish problem that is *really* hard to google for.