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'
endNext, 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.