Question

I have two classes:

class User
  include Mongoid::Document

  has_one :preference
  attr_accessible :name
  field :name, type: String
end

class Preference
  include Mongoid::Document

  belongs_to :user
  attr_accessible :somepref
  field :somepref, type: Boolean
end

And I have two factories:

FactoryGirl.define do
  factory :user do
    preference
    name 'John'
  end
end

FactoryGirl.define do
  factory :preference do
    somepref true
  end
end

After I create a User both documents are saved in the DB, but Preference document is missing user_id field and so has_one relation doesn't work when I read User from the DB.

I've currently fixed it by adding this piece of code in User factory:

after(:create) do |user|
  #user.preference.save! #without this user_id field doesn't get saved
end

Can anyone explain to me why is this happening and is there a better fix?

Was it helpful?

Solution

Mongoid seems to be lacking support here.

When FactoryGirl creates a user, it first has to create the preference for that new user. As the new user does not have an id yet, the preference can't store it either.

In general, when you try create parent & child models in one operation, you need two steps:

  1. create the parent, persist to database so it get's an id.
  2. create the child for the parent and persist it.

Step two would end up in an after(:create) block. Like this:

FactoryGirl.define do
  factory :user do
    name 'John'

    after(:create) do |user|
       preference { create(:preference, user: user) }
    end 
  end
end

OTHER TIPS

As stated in this answer:

To ensure that you can always immediately read back the data you just wrote using Mongoid, you need to set the database session options

consistency: :strong, safe: true

neither of which are the default.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top