This project is archived and is in readonly mode.
has_many through association does not link models on association save
-
Johannes Schmidt
- Tag changed from has_many_through to has_many_through, rails3
-
Johannes Schmidt
btw. using
post.people.create(:first_name => "Bob")works as expected.
-
Delineate
Just to clarify a little, I'm experiencing this in 2.3.5 on non-polymorphic has_many_through associations.
(The opening line suggests this is for polymorphic associations, though the example is not)Imho, the dropping of the intermediate model/association when saving the "built" child was very unexpected.
-
Johannes Schmidt
@Delinieate: Polymorphic was a typo. Just changed that.
-
Sigurd
From rails doc:
:autosave
If true, always save the associated object or destroy it if marked for destruction, when saving the parent object. **Off by default**.You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be aware of, mostly involving the saving of associated objects.
Unless you set the :autosave option on a has_one, belongs_to, has_many, or has_and_belongs_to_many association. Setting it to true will always save the members, whereas setting it to false will never save the members.
-
Johannes Schmidt
The same behavior when using the :autosave option.
-
Delineate
I've tried w/ various combinations of :autosave on different associations on the child=>intermediary=>parent relationships.
None seem to work.
Of course, :autosave on the parent => child associations aren't even needed if we were talking about saving the whole set by saving the parent.I have a feeling it's more a matter of the reverse relationship not being created in the first place.
child = parent.children.build() # Parent has the child associations parent.intermediaries => [<Intermediary id: 1....>] parent.children => [<Child id: 1 ...] # However, the child doesn't have the parent or intermediary. child.intermediaries => [] child.parent => [] # Thus, it's unlikely saving the child (w/ or w/out :autosave) will change this child.save child.intermediaries => [] child.parent => [] # Still empty.On the one hand, I suppose it shouldn't be assumed that the child => parent associations have been defined just because the parent=>child associations have been (which are necessarily exist if we're using build() in the first place ),
On the other, it seems very counter-intuitive that the only way to save the child correctly is to save the parent.
My guess is it's something that never made it off the TODO list.
-
joost baaij
I can confirm that this bug exists in 2.3.5 as well as master, and that adding autosave => true does not help.
IMO it's truly a bug since the intermediary model is built in memory automatically, but never saved when the child is saved.
-
Joe None
Also confirming bug exists in Rails beta3
-
Neeraj Singh
I looked into issue and this is what I found.
Let's say that relationship is
class Person < AR has_many :readers has_many :posts, :through => :readers end post = Person.first.posts.build(:quality => 'good') puts post.person_id #=> 8As you can see in the above case the relationship already exists. It's just that when post.save is called then no after_save callback is made to persist a new reader record.
In the after_save callback following two lines are needed. These two lines create the association record when you create a new post using Person.last.posts.create(..)
through_association = @owner.send(@reflection.through_reflection.name) through_record = through_association.create!(construct_join_attributes(record))However I am stuck. I am stuck because I do not know how to set an after_save callback on a given instance of post record. In this case there is no such after_save callback on the Post class. It is just that if a post instance is crated using build then those instances need an after_save callback to persist the association record.
Long writeup. However I wanted to explain everything I did. Someone who has more intimate knowledge of ActivRecord and a better ruby user should be able to fix it.
-
Ryan Bigg
- Tag changed from has_many_through, rails3 to bugmash, has_many_through, rails3
- State changed from new to incomplete
Please provide a failing test case and patch for this issue.
-
joost baaij
The failing test case is right there in the ticket.
Also here:
http://github.com/tilsammans/rails/commit/e613561734afb08cccae048d2... -
Lake
After applying "test_associate_by_saving_association.diff", included in the OP, I can confirm it's failing on master.
-
Ryan Bigg
Also bitten by this bug on 3.0.3. See http://github.com/radar/account_users_bug.
-
Repository
- State changed from incomplete to resolved
(from [91fd6510563f84ee473bb217bc63ed598abe3f24]) Allow building and then later saving has_many :through records, such that the join record is automatically saved too. This requires the :inverse_of option to be set on the source association in the join model. See the CHANGELOG for details. [#4329 state:resolved] https://github.com/rails/rails/commit/91fd6510563f84ee473bb217bc63e...
