Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-3291

Clear inverse associations when setting across all association types

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 8.0.1
    • Affects Version/s: None
    • Component/s: Associations
    • None
    • Minor Change
    • None
    • None
    • None
    • None
    • None
    • 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.

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            Kris-LIBIS Kris-LIBIS [X]
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              None
              None
              None
              None