Unexpected behaviour of << in has_many association #2422

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

Comments

Projects
None yet
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

This comment has been minimized.

Show comment
Hide comment
@wiehann

wiehann Jan 31, 2012

Contributor

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">]
Contributor

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

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Feb 1, 2012

Contributor

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

Contributor

kennyj commented Feb 1, 2012

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

@kennyj

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Feb 2, 2012

Contributor

@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.

Contributor

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

This comment has been minimized.

Show comment
Hide comment
@rubymaniac

rubymaniac Feb 3, 2012

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 :)

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

This comment has been minimized.

Show comment
Hide comment
@kennyj

kennyj Feb 3, 2012

Contributor

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

Contributor

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