Skip to content

Unexpected behaviour of << in has_many association #2422

Closed
rubymaniac opened this Issue Aug 4, 2011 · 5 comments

3 participants

@rubymaniac

Suppose we have a Parent object that has a has_many relationship with the Child model. The unexpected behaviour of << is that it lets me to add the same object twice i.e.

parent = Parent.new
first_child = Child.new(:name => "claire")
second_child = Child.new(:name => "john")
parent.childs << [first_child, second_child, second_child]
# => [Child#1, Child#2, Child#2]

which shouldn't happen imo because you are creating a wrong @target instance variable. To illustrate this if I try and save the parent and then call parent.childs it returns the three child objects with the duplicate of second_child

parent.childs
# => [Child#1, Child#2, Child#2]

If I restart the session then it reads them from the DB and all works as expected returning just the two objects

parent.childs
# SELECT `childs`.* FROM `childs` WHERE `childs`.`parent_id` = 8
# => [Child#1, Child#2]

I suggest not to let duplicate objects to exist in the collection.

@wiehann
wiehann commented Jan 31, 2012

That is the expected behaviour as the object has been loaded from the DB, and the cached version is returned.

class Book < ActiveRecord::Base
  has_many :chapters
end

class Chapter < ActiveRecord::Base
  belongs_to :book
end

book = Book.new(:name => "The Essential Rumi")
chapter_1 = Chapter.new(:title => "The Tavern")
chapter_2 = Chapter.new(:title => "Bewilderment")
book.chapters << [chapter_1, chapter_2, chapter_2]
book.save

book.chapters
# => [#<Chapter id: 21, book_id: 19, title: "The Tavern">, #<Chapter id: 22, book_id: 19, title: "Bewilderment">, #<Chapter id: 22, book_id: 19, title: "Bewilderment">]

To override this behavior, pass the (force_reload = true) argument.

book.chapters(force_reload = true)
# => [#<Chapter id: 21, book_id: 19, title: "The Tavern">, #<Chapter id: 22, book_id: 19, title: "Bewilderment">]
@kennyj
kennyj commented Feb 1, 2012

Agree. I think that this behavior is expected, and this issue is not rails's bug.

@kennyj
kennyj commented Feb 2, 2012

@rubymaniac
I'm closing this issue, because It seems that this is not rails's bug (expected behavior).
If you have any problem, please comment this issue.

@kennyj kennyj closed this Feb 2, 2012
@rubymaniac

Well, mine expected behaviour is apparently different from what you think as expected. I would expect it to behave more like a Set and less like an Array. But anyway, I agree that most people would expect the current behaviour, so you did best closing this issue :)

@kennyj
kennyj commented Feb 3, 2012

Certainly, A has_many's collection is so-called 'List'. but not 'Set' ... :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.