0

Assume that I have a city model where:

class city
  field :full_name, type: String # San Francisco, CA, United States
  field :_id, type: String, overwrite: true, default: ->{ full_name }
end

Assume that I have a factory defined in /spec/factories/cities.rb:

FactoryGirl.define do
  factory :city do
    full_name 'San Francisco, CA, United States'
  end
end

Running the following code in one of the specs:

city_attrs = { full_name: 'San Francisco, CA, United States' }
City.create! city_attrs
=> #<City _id: San Francisco, CA, United States, full_name: "San Francisco, CA, United States">

FactoryGirl.create(:city)
=> #<City _id: , full_name: "San Francisco, CA, United States">

How do I fix this without adding the following code to the /spec/factories/cities.rb?

before(:create) do |city, evaluator|
  city.id = city.full_name
end

EDIT the solution is to stop using FactoryGirl and use Fabrication instead as recommended in this answer

Community
  • 1
  • 1
a14m
  • 7,808
  • 8
  • 50
  • 67
  • Why not just add that code? – Matt Gibson Oct 21 '13 at 12:30
  • in some cases the model will have call back procedures that will alter a lot of it's attributes... i want the `FactoryGirl` create to follow this call backs instead of providing these kind of call backs in the `before(:create)` – a14m Oct 21 '13 at 12:37
  • if you are not using `ActiveRecord` could you please at least mention the database adapter you are using? – phoet Oct 21 '13 at 13:17
  • did you try calling [apply_defaults](https://github.com/mongoid/mongoid/blob/master/lib/mongoid/fields.rb#L91) ? – phoet Oct 21 '13 at 16:00
  • `apply_defaults` didn't work – a14m Oct 21 '13 at 16:23

2 Answers2

1

You need to override the initialization of the model used by FactoryGirl:

FactoryGirl.define do
  trait :explicit_initialize do
    initialize_with { new(attributes) }
  end

  factory :city, traits: [:explicit_initialize] do
    full_name 'San Francisco, CA, United States'
  end

end
marquez
  • 737
  • 4
  • 10
0

Like explain on documentation, all default define in lambda are lazy. So you need pre_process it :

When defining a default value as a proc, Mongoid will apply the default after all other attributes are set. If you want this to happen before the other attributes, set pre_processed: true.

class city
  field :full_name, type: String # San Francisco, CA, United States
  field :_id, type: String, overwrite: true, pre_processed: true, default: ->{ full_name }
end
a14m
  • 7,808
  • 8
  • 50
  • 67
shingara
  • 46,608
  • 11
  • 99
  • 105