-
Type:
Bug
-
Resolution: Done
-
Priority:
Minor - P4
-
Affects Version/s: None
-
Component/s: Associations
-
None
MongoDB version: 2.4.6
Mongoid gem: 3.1.5
Mongo gem: 1.9.2
Moped gem: 1.5.2
JRuby 1.7.4
OS: 64-bit Linux
I can update a 1-N (belongs_to - has_many) relationship on the side that has the belongs_to relation, but not on the side that has the has_many relation.
Given this:
class Book include Mongoid::Document field :name belongs_to :shelf def to_s() self.name; end def status() "#{name} on #{shelf || 'floor'}"; end end class Shelf include Mongoid::Document field :name has_many :books def to_s() self.name; end def status() "#{name} : [#{books.join(',')}]"; end end
The user scenario is:
def status puts "#{'%3.3d' % @i} - #{@book1.status} - #{@book2.status}" puts " #{@shelf1.status} - #{@shelf2.status}" @i+= 1 end status move @book1, @shelf1 move @book2, @shelf2 move @book1, @shelf2 move @book2, @shelf1
This works:
def move(book, shelf) puts "Moving #{book} to #{shelf}" book.shelf = shelf book.save! status end
000 - book1 on floor - book2 on floor shelf1 : [] - shelf2 : [] Moving book1 to shelf1 001 - book1 on shelf1 - book2 on floor shelf1 : [book1] - shelf2 : [] Moving book2 to shelf2 002 - book1 on shelf1 - book2 on shelf2 shelf1 : [book1] - shelf2 : [book2] Moving book1 to shelf2 003 - book1 on shelf2 - book2 on shelf2 shelf1 : [] - shelf2 : [book2,book1] Moving book2 to shelf1 004 - book1 on shelf2 - book2 on shelf1 shelf1 : [book2] - shelf2 : [book1]
But this doesn't:
def move(book, shelf) puts "Moving #{book} to #{shelf}" shelf.books << book shelf.save! book.save! status end
000 - book1 on floor - book2 on floor shelf1 : [] - shelf2 : [] Moving book1 to shelf1 001 - book1 on shelf1 - book2 on floor shelf1 : [book1] - shelf2 : [] Moving book2 to shelf2 002 - book1 on shelf1 - book2 on shelf2 shelf1 : [book1] - shelf2 : [book2] Moving book1 to shelf2 003 - book1 on shelf2 - book2 on shelf2 shelf1 : [book1] - shelf2 : [book2,book1] Moving book2 to shelf1 004 - book1 on shelf2 - book2 on shelf1 shelf1 : [book1,book2] - shelf2 : [book2,book1]
Notice how moving a book works only partially: The new shelf and the book know the book has moved, but the old shelf does not know the book is removed.
What seems to fix this is to remove the book from the old shelf first. Unfortunately
old_shelf = book.shelf if old_shelf old_shelf.delete book old_shelf.save! book.save! end
does not seem to remove the book from the shelf. Only this does:
book.shelf = nil
book.save!
... and that brings us back to the issue at hand.