collection << on new_record? == false (hm:t) can be deferred?

hi everyone, in this example I'm going to use a simple has_many :through association.

Browsing Rails' source I noticed that assigning some objects to a collection when the record is new and then saving, I can pass every kind of object, which passes validate_associated or not:

@test = Report.new({"document_id"=>nil, "created_at"=>nil, "updated_at"=>nil, "when"=>nil})

=> #<Report id: nil, document_id: nil, when: nil, created_at: nil, updated_at: nil>

@test.reasons << Reason.find_or_create_by_content("pr") # invalid records mass fest, validation will occur on save

=> [#<Reason id: nil, content: "pr", created_at: nil, updated_at:

]

@test.save

=> false # all green

On the contrary when the object (owner) is already in place, it bombs out with an exception.

@test = Report.first

=> #<Report id: 1, document_id: 1, ...

@test.reasons << Reason.find_or_create_by_content("pr") # ACK

ActiveRecord::RecordInvalid: Validation failed: Content is too short (minimum is 3 characters)

Nothing strange, I'm sure that's the correct behaviour, what I would like to ask is if there's some chance to "defer" the assignment, i.e. acknowledge @test that he will have some reasons but do not raise if some of them are invalid, leaving the job to update_attributes in controller.

Would be a patch useful, if currently there are no ways, regarding this matter?

Would be a patch useful, if currently there are no ways, regarding this matter?

It sucks that this is inconsistent, but I think this is probably going to be a pretty tough problem for you to solve with a patch. Because the presence of an object in the has_many :through collection requires the existence of a record in the association table. Figuring out how to handle the different permutations of validation methods along the chain will probably be a little difficult.

In your case you could probably try either using the full set of associated classes (i.e. creating the ReportReason object in your controller). Or alternatively create and validate the reason object on its own.

Mixing transient and persistent objects in a single graph leads to some strange issues like this, so you're probably better off avoiding the potential problems altogether.