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

"dependent: :destroy" option destroys out-of-date relation

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 7.0.0
    • Affects Version/s: 5.0.0
    • Component/s: None
    • None
    • Environment:
      {OS: "OS X 10.10.5", Rails: 4.1.7, Mongoid: 5.0.0}

      Setup

      Consider the has_one/belongs_to relation between the Parent and Child classes, noting that the :dependent option is set to destroy:

      parent.rb
      class Parent
        include Mongoid::Document
        has_one :child, :dependent => :destroy
        field :name, :type => String
      end
      
      child.rb
      class Child
        include Mongoid::Document
        belongs_to :parent
        field :name, :type => String
      end
      

      Repro Steps

      1. Create two Parent instances, p1 and p2
      2. Create one Child instance c, assigning p1 as c's parent
      3. Re-assign c to p2} (not the same as assigning {{p2 to c)
      4. Call #save() on p2 (not the same as calling #save() on c)
      4. Note that c is currently in the DB
      5. Destroy p1
      6. Note that c is no longer in the DB

      Rails Console Example

      2.2.2 :001 > p1 = Parent.create!(:name => 'Penny')
       => #<Parent _id: 56f3299e211d7003eb000003, name: "Penny">
      2.2.2 :002 > p2 = Parent.create!(:name => 'Paige')
       => #<Parent _id: 56f329a4211d7003eb000004, name: "Paige">
      2.2.2 :003 > c = Child.create!(:name => 'Cindy', :parent => p1)
       => #<Child _id: 56f329a8211d7003eb000005, parent_id: BSON::ObjectId('56f329a4211d7003eb000004'), name: "Cindy">
      2.2.2 :004 > p2.child = c
       => #<Child _id: 56f329a8211d7003eb000005, parent_id: BSON::ObjectId('56f329a4211d7003eb000004'), name: "Cindy">
      2.2.2 :005 > p2.save!
       => true
      2.2.2 :006 > Child.find(c.id)
       => #<Child _id: 56f329a8211d7003eb000005, parent_id: BSON::ObjectId('56f329a4211d7003eb000004'), name: "Cindy">
      2.2.2 :007 > p1.destroy!
       => true
      2.2.2 :008 > Child.find(c.id)
       => nil
      

      Why Does This Need Fixing?

      There is at least one workaround for this (e.g. call #save() on c instead of p2). However, I can attest that it can be difficult for developers to detect when this bug has manifested and understand that a workaround is even required.

            Assignee:
            emily.stolfo Emily Stolfo
            Reporter:
            shealen.clare@gmail.com Shealen Clare
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: