mongoid/mongoid — Issue #1372: Safe mode + find_or_create_by + presence validation error
Author: dbackeus
Created: 2011-10-22 12:37:59+00:00
State: open

Attempting to find_or_create_by and association which presence is validated in safe mode results in a duplicate index error:

```
/Users/druiden/.rvm/gems/ruby-1.9.2-p290/gems/mongo-1.4.1/lib/mongo/connection.rb:450:in `send_message_with_safe_check': 11000: E11000 duplicate key error index: test.children.$_id_ dup key: { : ObjectId('4ea2b851541290074b000002') } (Mongo::OperationFailure)
```

Reproduce with:

``` ruby
Mongoid.persist_in_safe_mode = true

class Parent
include Mongoid::Document

has_many :children, :dependent => :destroy
end

class Child
include Mongoid::Document

belongs_to :parent

validates_presence_of :parent # Remove this and the error doesn't happen
end

Child.find_or_create_by(:parent_id => Parent.create.id)
```

Error backtrace:

```
/Users/druiden/.rvm/gems/ruby-1.9.3-rc1/gems/mongo-1.4.1/lib/mongo/connection.rb:450:in `send_message_with_safe_check': 11000: E11000 duplicate key error index: test.children.$_id_ dup key: { : ObjectId('4ea2b7ad54129006f6000002') } (Mongo::OperationFailure)
from gems/mongo-1.4.1/lib/mongo/collection.rb:945:in `block in insert_documents'
from gems/mongo-1.4.1/lib/mongo/util/logging.rb:23:in `instrument'
from gems/mongo-1.4.1/lib/mongo/collection.rb:943:in `insert_documents'
from gems/mongo-1.4.1/lib/mongo/collection.rb:342:in `insert'
from gems/mongoid-2.3.2/lib/mongoid/collections/master.rb:25:in `block in insert'
from gems/mongoid-2.3.2/lib/mongoid/collections/retry.rb:29:in `retry_on_connection_failure'
from gems/mongoid-2.3.2/lib/mongoid/collections/master.rb:24:in `insert'
from gems/mongoid-2.3.2/lib/mongoid/collection.rb:98:in `insert'
from gems/mongoid-2.3.2/lib/mongoid/persistence/operations/insert.rb:27:in `block in persist'
from gems/mongoid-2.3.2/lib/mongoid/persistence/insertion.rb:26:in `block (3 levels) in prepare'
from gems/activesupport-3.1.1/lib/active_support/callbacks.rb:390:in `_run_create_callbacks'
from gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81:in `run_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:42:in `block in run_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:67:in `call'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:67:in `run_cascading_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:41:in `run_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/persistence/insertion.rb:25:in `block (2 levels) in prepare'
from gems/activesupport-3.1.1/lib/active_support/callbacks.rb:390:in `_run_save_callbacks'
from gems/activesupport-3.1.1/lib/active_support/callbacks.rb:81:in `run_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:42:in `block in run_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:67:in `call'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:67:in `run_cascading_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/callbacks.rb:41:in `run_callbacks'
from gems/mongoid-2.3.2/lib/mongoid/persistence/insertion.rb:24:in `block in prepare'
from gems/mongoid-2.3.2/lib/mongoid/persistence/insertion.rb:22:in `tap'
from gems/mongoid-2.3.2/lib/mongoid/persistence/insertion.rb:22:in `prepare'
from gems/mongoid-2.3.2/lib/mongoid/persistence/operations/insert.rb:26:in `persist'
from gems/mongoid-2.3.2/lib/mongoid/persistence.rb:44:in `insert'
from gems/mongoid-2.3.2/lib/mongoid/persistence.rb:149:in `upsert'
from gems/mongoid-2.3.2/lib/mongoid/persistence.rb:172:in `block (2 levels) in create'
from gems/mongoid-2.3.2/lib/mongoid/persistence.rb:172:in `tap'
from gems/mongoid-2.3.2/lib/mongoid/persistence.rb:172:in `block in create'
from gems/mongoid-2.3.2/lib/mongoid/threaded/lifecycle.rb:156:in `_creating'
from gems/mongoid-2.3.2/lib/mongoid/persistence.rb:171:in `create'
from gems/mongoid-2.3.2/lib/mongoid/finders.rb:149:in `find_or'
from gems/mongoid-2.3.2/lib/mongoid/finders.rb:97:in `find_or_create_by'
```

Was introduced when I switched from 2.2.x to 2.3.x. I'm running ruby 1.9.3.rc1 but confirmed the bug with the latest 1.9.2 as well.