#130 ✓resolved
David Lee

Strange has_many association behavior

Reported by David Lee | January 6th, 2008 @ 04:18 AM

Basically, the schema I have setup is:

User:

has_many :items

Item:

belongs_to :user

The behavior of user.items does not behave correctly as follows:

x = User.new

x.save

x.items << Item.new

x.items << Item.new

x.save

x.reload

x.items # <== CORRECT: has two items

x.items = []

x.save

x.reload

x.items # <== INCORRECT: still has two items

x.items.delete_at 1

x.items # <== has one item

x.save

x.reload

x.items #<== INCORRECT: has 0 items

I'm not sure what the problem is. Maybe associations are not yet fully supported?

Comments and changes to this ticket

  • Kevin Bullock

    Kevin Bullock January 6th, 2008 @ 09:29 PM

    I've written a spec example to prove this bug. Patch attached.

    Can ActiveRecord take such behavior? At least an error should be raised if there's another preferred way to clear-and-reassign the association collection. It would seem to make sense the way David is doing it though.

  • Kevin Bullock

    Kevin Bullock January 6th, 2008 @ 09:53 PM

    As to the second half of the bug (the call to #delete_at onward), I'm only getting a NoMethodError; the association collection doesn't have a #delete_at method. (using r685)

  • Kevin Bullock

    Kevin Bullock January 6th, 2008 @ 10:32 PM

    Improved the spec... it shows that assigning [] to the collection and then saving doesn't delete or dissociate the objects in the database. I'm not sure what the appropriate behavior should be: on a has_many, is this an implicit #destroy! ? That probably wouldn't be right unless the corresponding belongs_to association were mandatory (i.e., don't delete the objects in my collection unless they're totally dependent on me!).

  • David Lee

    David Lee January 7th, 2008 @ 12:57 AM

    I just tried it again and I can verify that the #delete_at method exists & works as it does in arrays.

    Also, this inconsistent behavior of associations is what caused me much troubles with AR. Sometimes associations would be correctly saved to the database. Other times, it would not.

    I suggest either completely supporting the association so that it actually is like a property of the original object ("user" in my example), or to make it only a getter so that it returns an array (not association collection) of the associated objects (each requiring their own #save to be called in order for them to be properly reflected in the database).

    As for the behavior of the has_many right now, setting the assocation to [Item[1], Item[2]] and then setting it to [Item[1]] leaves Item[2] in the items table but without the user_id. So it's not destroying nor deleting but just disassociating.

  • Kevin Bullock

    Kevin Bullock January 7th, 2008 @ 09:45 AM

    Strange. What does user.items say its class is? And just to verify, are you running from trunk, or from the 0.2.5 gem?

  • Sam Smoot

    Sam Smoot January 7th, 2008 @ 08:55 PM

    • State changed from “new” to “open”

    Also, might want to make sure habtm uses a TypedSet as part of this ticket. It can make debugging easier anyways.

  • Dan Kubb (dkubb)
  • Sam Smoot

    Sam Smoot May 21st, 2008 @ 01:22 AM

    I believe this is resolved, but just in case, no harm in adding the spec to SVN/DM.

    Adam, can thou taketh care of?

  • Sam Smoot

    Sam Smoot June 2nd, 2008 @ 06:31 PM

    • Assigned user set to “Adam French”
  • Adam French

    Adam French June 10th, 2008 @ 11:06 AM

    The spec still fails.

    The suggested way of emptying an associations was to call #clear on it. I'll whip something up that inspects the incoming variable and calls #clear if the value is empty

  • Adam French

    Adam French June 10th, 2008 @ 11:39 AM

    • State changed from “open” to “resolved”

    I just patched in support for clearing and deactivating the association when it's assigned an empty array. This resolves the issue raised in the spec.

    Please let us know if this solves your problem!

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

People watching this ticket

Pages