Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I define associated Factories with FactoryBot?

Given two models, Alert and Zipcode, where one Alert must have 1 or more Zipcodes:

class Alert < ActiveRecord::Base
  attr_accessible :descr, :zipcode

  has_many :zipcode
  validates :zipcode, :length => { :minimum => 1 }
end

class Zipcode < ActiveRecord::Base
  attr_accessible :zip
  belongs_to :alert
end 

How do I write my FactoryBot factories so that:

  • Zipcode factories are defined in their own file
  • Alert factories are defined in their own file
  • Alert can rely on the factory defined by Zipcode?

All of the documentation and examples I read expect you to define the contained class inside the parent factory file, blob them all together, or make some other compromise or work-around. Isn't there a clean way to keep the spec factories separate?

like image 445
JD. Avatar asked Aug 24 '12 23:08

JD.


People also ask

What is trait in FactoryBot?

FactoryBot's traits are an outstanding way to DRY up your tests and factories by naming groups of attributes, callbacks, and associations in one concise area. Imagine defining factories but without the attributes backed by a specific object.

What is factory in RSpec?

RSpec provides an easy API to write assertions for our tests, while Factory Bot allows us to create stubbed in data for our tests.

What is Build_stubbed?

build_stubbed imitates creating. It slubs id , created_at , updated_at and user_id attributes. Also it skips all validations and callbacks. Stubs means that FactoryBot just initialize object and assigns values to the id created_at and updated_at attributes so that it just looks like created.


1 Answers

The trick is to make sure the container class, that is, the one with a has_many statement in its definition, creates the contained class as an array in FactoryBot. For example:

In your spec/factories/zipcodes.rb:

FactoryBot.define do
  factory :zipcode do
    zip { 78701 + rand(99) } 
  end
end

And in spec/factories/alerts.rb:

FactoryBot.define do
  factory :alert do
    zipcode { Array.new(3) { FactoryBot.build(:zipcode) } }
  end
end
like image 198
JD. Avatar answered Nov 01 '22 06:11

JD.