This project is archived and is in readonly mode.
Adding records to a has_many collection does not work on initialization
-
josh
- Assigned user set to josh
I wrote up some ActiveRecord tests for it, however they are passing for me. Did you try this on edge? Or are my test cases not covering the same thing you are referring too?
-
josh
- State changed from new to open
-
Simon Jefford
I've had a quick poke around with this and I can't seem to get a failing test either. However, I was able to replicate the problem in a Rails app using the exact models and code described by zargony.
-
Simon Jefford
I can only get this to happen inside script/console.
Again, using the models described by Andreas, I ran the following using script/runner:
u = User.new(:username => 'foo', :email => 'foo@bar.baz') u.email_addresses u.save! puts u.email_addresses.first.addressand got
-
Andreas Neuhaus
Interestingly, the test also passes for me. But the bug still occurs when using the console of a project where I disabled the described workaround.
Though I don't see why, there must be something wrong with the test. I'll do some more tests later today.
-
Andreas Neuhaus
Joshua: yes, I'm trying with rails edge pulled from git.
The problem occurs, if you create an object of a model which builds associated objects during initialization. If you access these associated objects before saving the object itself, all associated objects are lost.
I guess, that this problem might be related to the lazy-loading of an associated collection. If an object builds associated objects in its initializer, the association is still marked as loaded?==false; so on first access to the association proxy, it'll try to load the collection and wipes the ones built in memory.
For some reason, it looks like accessing email_addresses.first is ok, but accessing email_addresses or doing email_addresses.inspect results in an empty array:
>> u=User.new(:username=>'foo', :email=>'foo@bar.baz') => #<User id: nil, username: "foo", created_at: nil, updated_at: nil> >> u.email_addresses.loaded? => false >> u.email_addresses.first => #<EmailAddress id: nil, address: "foo@bar.baz", user_id: nil, created_at: nil, updated_at: nil> >> u.email_addresses.loaded? => true >> u.email_addresses => [#<EmailAddress id: nil, address: "foo@bar.baz", user_id: nil, created_at: nil, updated_at: nil>] >> ?> u=User.new(:username=>'foo', :email=>'foo@bar.baz') => #<User id: nil, username: "foo", created_at: nil, updated_at: nil> >> u.email_addresses.loaded? => false >> u.email_addresses => [] >> u.email_addresses.loaded? => trueI can reproduce this with script/console and with script/runner, but for some reason not with a test...
-
Andreas Neuhaus
I think I finally tracked it down. It's the inspect method of AssociationProxy that does a reload if the target isn't loaded yet and therefore wipes the collection in this case.
The console automatically does #inspect to display an object. That's why it always happened in the console but not in tests.
I attached a patch that fixes this problem and adds a proper test.
Unfortunately, I cannot reopen this ticket myself.
-
Michael Koziarski
- State changed from hold to open
-
Repository
- State changed from open to resolved
(from [bcb090c56b842a76397e0ea32f54c942fd11910e]) Calling ActiveRecord#inspect on an unloaded association won't wipe the collection [#9 state:resolved]
Signed-off-by: Joshua Peek
