Lesson Tuesday

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.

Using Faker


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:

db/seeds.rb
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.)

Note on 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.

More Faker Functionality

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