Terminology:
...
means "whatever else is already here", don't actually input three dots!
To get started, add the following gem in your Gemfile in the :development, :test
group, and run 'bundle update'
group :development, :test do
...
gem 'factory_bot_rails'
end
Next, alter /spec/rails_helper.rb
, locate the RSpec.configure
block and enter the code as found below.
This tells FactoryBot to reload all objects after each test (helpful if you use before :each
blocks. The config.include
line makes all FactoryBot commands available without prefixing them all, so we can use create()
instead of FactoryBot.create()
Next, create /spec/factories/
as a folder. For this example, we're going to create factories for a User
model and an Item
model. We'll assume users have different roles and can be made active or inactive, etc.. Items will also have an active/inactive flag, a price, quantity, etc.
Next, create /spec/factories/user.rb
for our User model, and enter the code from the file below.
This creates three different factories around the User model. The first factory, :user
will generate a known string for the user's name, email and password, set their role
to an integer of 0, and set their :active
flag to true
.
The second factory is called :inactive_user
and uses :user
as a "parent" template, which copies all attributes from that parent factory. This second factory, then, overrides the name and email address, and also overrides their :active
flag to be false.
The last factory here is called :admin
, which overrides the name, email and role. This also forces the :active
flag to true
in case we ever set the :user
factory otherwise.
The next factory we're going to make will be for items. Create a new file called /spec/factories/item.rb
and enter the code from the file below.
Similar to the :user
factory, we can now generate an active :item
, or we can use :inactive_item
to generate an item with the :active
flag overridden to a false
state.
Items can also have a numeric price, but this code looks a little strange. We'll discuss that when we read about sequences below.
How to use these factories
user = create(:user)
This generates an instance of the User
model and set the appropriate fields. Since we're only creating one of these, their email address will be [email protected]
, their name will be User Name 1
etc.
Calling this a second time will increment the 'sequence' number (more on sequences below), so calling the create() method a second time will generate a user whose email address will be [email protected]
etc..
When we create an item, we see that the sequence does some math for us with the price and quantity. Our factory says "whatever the sequence is, add 1 to it, then multiply that number by 1.5 to set its price. Therefore, the first item we create()
will have a price of $3.00, the second item will have a price of $4.50, and so on.
The nice thing about FactoryBot is that we can also generate lots of these objects in one shot.
user_1, user_2, user_3 = create_list(:user, 3)
Here, we use create_list()
to make an array of these objects. We can also assign them to an array:
a_whole_lot_of_users = create_list(:user, 100)
What are sequences?
FactoryBot will allow us to make one or more items and increment a counter. This comes in really handy for giving every user a unique name or email address, or use different images, etc..
However, as you noticed in the :item
factory, FactoryBot's sequence generator doesn't handle numbers in a clean way so we have to do some Ruby code to string interpolate the sequence number, then turn that into a numeric data type.