In order to properly use and test database scopes, it's useful to have lots of objects in our database. While we can do this manually, it quickly becomes tedious, especially if we want to add hundreds (or even more) records to our database.
Fortunately, the Faker gem can create fake data for us so we can seed it to our database. We can install it by adding gem 'faker'
to our Gemfile
, then bundling.
Here’s a potential use case. Let’s say we have a recipe site and we want to include a section on spices. Our database has a spices
table with the following fields: name
, description
and image_url
. We can randomly add fifty spices to our database by doing the following:
Spice.destroy_all
50.times do |index|
Spice.create!(name: Faker::Food.spice,
description: Faker::Lorem.sentence(20, false, 0).chop,
image_url: "site.com/here_is_a_picture_of_cardamom.jpg")
end
p "Created #{Spice.count} spices"
First, we clear out all instances of the Spice
object before we seed the database. Our loop runs fifty times, creating spices in the process. Faker will generate a name
and description
for each object. Conveniently, Faker has a food class that includes spices. For the description
, we generate twenty words of lorem ipsum text.
We’ve also added an image_url
, though it generates the same image for every record. (If you have the chance, see if you can figure out a way to generate random images in your seed file.)
create!
Note that we use create!
here, the bang version of create
. So what's the difference? If there is an error at any point during seeding, using create!
will raise an exception and the database will stop seeding. (All records seeded before the exception will remain in the database, however.) If we were to use create
instead, the seeds.rb code will run to completion but creation of some (or even all) records may silently fail.
So when will using create!
throw an exception? Well, there could be a number of causes, but in our case, the most likely reason is is that a record failed to validate. Remember, validations apply to all records, regardless of whether they're created in the application, in the Rails console, or even in a seed file.
If a record fails to seed because it isn't validated, create!
will throw the specific validation error. To properly fix this issue, you should update your seeds.rb code so that all records can properly be validated and created in the database. Using create
instead isn't a good solution; after all, if we ask our seeds.rb file to create 100 records in the database, it should do so, not silently fail sometimes.
Returning to our project, after the loop, we'll print a line of code to the console that confirms we created fifty spices. Now we can run $ rake db:seed
in the terminal, populating the database with our new objects.
Check out the Faker's documentation to learn more about its other classes. In addition to generating names, addresses, numbers and other useful things, Faker has quirky classes such as Star Wars, Pokemon, and even Chuck Norris.
You can also write code that will allow you to add fake nested objects so you can build out all your relationships. See if you can figure out how to do this on your own. You will need a nested loop to do this. You will be expected to seed the database with nested objects on the code review. Keep in mind that by default Rails 5 requires objects with a belongs_to
relationship to actually belong to another object in a one-to-many relationship. You will need to randomize the association_id
for the nested object so that it's actually associated to another object.
You'll also need to do some tinkering if you want to randomize the created_at
and updated_at
timestamps that Rails provides. These can't be randomized at creation; instead, you can update them with randomized data using update_attributes
.
Keep in mind that your database will fail to save any records that don't pass validations. This includes seeded records!
Faker isn’t just helpful with testing and using database scopes. It also helps us create a mock-up of our site. For instance, if our site is a virtual store, we could quickly create hundreds of products so that our products pages aren't empty. This comes in handy when we want to demo an application to friends, family and employers.
Lesson 27 of 34
Last updated July 14, 2022