mongoid/mongoid — Issue #1442: adding a replacement child via has_one doesn't delete original child
Author: jasonsydes
Created: 2011-11-21 07:09:04+00:00
State: open

Hi,

I'm somewhat new to Mongoid and MongoDB, my apologies if this doesn't actually turn out to be a bug.

I'm using version 2.3.3 of Mongoid on Lion OS X, and here's the version of MongoDB that I'm using:

```
∴ mongod --version
db version v2.0.0, pdfile version 4.5
Sun Nov 20 22:35:17 git version: 695c67dff0ffc361b8568a13366f027caa406222
```

When using has_one/belongs_to, and when replacing one belongs_to object with another, it looks like Mongoid is not destroying the replaced child.

Given:

```ruby
## A is parent of B
class A
include Mongoid::Document
has_one :b, dependent: :destroy, autosave: true
end

class B
include Mongoid::Document
belongs_to :a
end

## C is parent of D
class C
include Mongoid::Document
embeds_one :d
end

class D
include Mongoid::Document
embedded_in :c
end
```

When using has_one/belongs_to, I'm seeing the incorrect behavior:

```
ruby-1.9.2-p180 :055 > a = A.create!
#
ruby-1.9.2-p180 :056 > a.create_b
#
ruby-1.9.2-p180 :057 > a.create_b
#
ruby-1.9.2-p180 :058 > B.all.to_a
MONGODB db_dev['bs'].find({})
[
[0] #,
[1] #
]
```

And here's a dump of the A and B collections via mongoexport:

```
∴ mongoexport --db db_dev --collection as
connected to: 127.0.0.1
{ "_id" : { "$oid" : "4ec9f0cea9ffd1dee200000a" } }
exported 1 records
∴ mongoexport --db db_dev --collection bs
connected to: 127.0.0.1
{ "_id" : { "$oid" : "4ec9f0d2a9ffd1dee200000b" }, "a_id" : { "$oid" : "4ec9f0cea9ffd1dee200000a" } }
{ "_id" : { "$oid" : "4ec9f0d5a9ffd1dee200000c" }, "a_id" : { "$oid" : "4ec9f0cea9ffd1dee200000a" } }
exported 2 records
```

In contrast, when using embeds_one/embedded_in, I see correct behavior:

```
ruby-1.9.2-p180 :059 > c = C.create!
#
ruby-1.9.2-p180 :060 > c.create_d
#
ruby-1.9.2-p180 :061 > c.create_d
#
ruby-1.9.2-p180 :062 > C.all.map{|c|c.d}
MONGODB db_dev['cs'].find({})
[
[0] #
]
```

And here's a dump of the A collection via mongoexport:

```
∴ mongoexport --db db_dev --collection cs
connected to: 127.0.0.1
{ "_id" : { "$oid" : "4ec9f0e5a9ffd1dee200000d" }, "d" : { "_id" : { "$oid" : "4ec9f0eda9ffd1dee200000f" } } }
exported 1 records
```

It doesn't seem to matter which method I use to create the B-child object: `a.create_b()` and `B.create!(a: a)` both produce the same behavior as show above.

Additionally, I get the same behavior whether I use either of the following:

```ruby
has_one :b, dependent: :destroy, autosave: true
```

or:

```ruby
has_one :b
```

Unfortunately, because the "foreign key" is kept in the child object, Mongoid doesn't realize that the newest child added is the correct one:

```
ruby-1.9.2-p180 :013 > a.b
MONGODB db_dev['bs'].find({"a_id"=>BSON::ObjectId('4ec9f0cea9ffd1dee200000a')}).limit(-1).sort([[:_id, :asc]])
#
```

Thanks!