Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FactoryGirl create_list pass in multiple values

If I have this factory:

factory :product, class: Product do
  name        { Faker::Commerce.product_name }
  description { Faker::Lorem.paragraph }
  price       { Faker::Number.number(3) }
end

I can use create_list to create 2 products like this:

FactoryGirl.create_list(:product, 2)

but I want to pass in defaults to both my products, I would suppose something theoretically like this?:

prods = [{:name => "Product 1"},{:name => "Product 2"}]
FactoryGirl.create_list(:product, prods.count, prods)

I have searched for a while and cannot find the answer to this, is it possible using an elegant solution like create_list?

The reason I would like this solution is because :product is one of many child associations to a parent model. I would like a configurable way that I could generate the parent model factory through a single FactoryGirl.create command and pass in all the values I would like for child associations (through the use of FactoryGirl's traits and ignore blocks). I hope that makes sense. I could show a bunch of code here but I believe this provides enough context?

like image 790
joshweir Avatar asked Jul 14 '15 07:07

joshweir


3 Answers

Since v5.2.0 you can do this:

twenty_somethings = create_list(:user, 10) do |user, i|
  user.date_of_birth = (20 + i).years.ago
end
like image 157
Emmanuel Gautier Avatar answered Nov 05 '22 08:11

Emmanuel Gautier


I found this thread looking for a similar solution. If you are actually just wanting to sequence the name like your example, you can use sequence in the factory and then create_list -- which I found could be used as a trait as well. My need was to increment a timestamp when creating a list of records:

trait :sequentially_longer_ago do
  sequence(:created_at) { |n| n.days.ago }
end

and then:

create_list(:my_record, 123, :sequentially_longer_ago, foo: 'bar')

So in your case, it might be:

trait :sequence_product_name do
  sequence(:name) { |n| "Product #{n + 1}" }
end

and then:

create_list(:product, 123, :sequence_product_name, foo: 'bar')
like image 20
Scott Gratton Avatar answered Nov 05 '22 07:11

Scott Gratton


You can generate the list yourself:

data = [{:name => "Product 1"},{:name => "Product 2"}]
products = data.map { |p| FactoryGirl.create(:product, p) }

Which should leave you with an array of products.

like image 13
mhutter Avatar answered Nov 05 '22 07:11

mhutter