Factories with factory_bot_rails and Faker

May 01, 2019

rails logo Rails

It's often helpful to see how our UI's scale with lots of data in them but seeding data manually in very slow. So using factory_bot_rails and Faker I'll show you how to make a whole lot of realistic data quickly.

First step install the gems. Add these gems to your Gemfile:



group :development, :test do
gem 'factory_bot_rails'
gem 'faker'
end

Next we'll need to setup our factories. A factory is an easily called snippet that creates a model for you. In general they are found in the test/ spec/ and factories/ directories. I generally put mine in spec/factories/model_name.rb. So for an an example model of a user, we might provide a firstname, lastname, Department (a belongs to relationship), and username.



# spec/factories/user.rb
FactoryBot.define do
factory :user do
firstname { 'John' }
lastname { 'Doe' }
department { Department.all[0] } # we're assuming a department exists here
username { 'cmw233' }
end
end

But this isn't great as it will create the same user every time. What if we want each user to be unique?

Enter Faker. Faker allows you to generate either deterministic (keeps your test cases consistent) to random-ish data of many many many types. Faker can generate names, addresses, phone numbers, countries, almost whatever you need. Here's how you call it.



fname = Faker::Name::first_name

And to see a full list of Faker's see this list.

Now combining the two ideas we can do something like this:



# spec/factories/user.rb
FactoryBot.define do
factory :user do
firstname { Faker::Name::first_name }
lastname { Faker::Name::last_name }
department { Department.all[0] }
username { Faker::Internet.username }
end
end

And with a little bit of ruby-foo outside of Factory Bot or Faker you can randomize the relationship by selecting a random # between 0 and the number of departments - 1.



department { Department.all[rand(0..Department.all.length-1)] }

Okay now that we have factories all set up lets call them from our seeds. We can either build or create a factory. Building a factory creates the model and fills the attributes, creating it does the same but it also saves. Here's what your seeds.rb could look like:



# db/seeds.rb
for x in 1..1000 do
FactoryBot.create(:user)
# create 1000 users and save them
end
special_user = FactoryBot.build(:user)
special_user.firstname = "Nate"
special_user.lastname = "who wrote this"
special_user.save! # without this the model wouldn't be saved to the db.