This is going to be a very straightforward article, no jokes included.
When you want to populate you database during development, you need to use a file that already comes in Rails: the seeds.rb file. You can find it inside the db folder, the same where you can find the migration and schema files.
Aside from that you'll need two gems: the Populator gem, and the Faker gem. The last one is not actually necessary, but makes your life a lot easier, and your dummy data much more realistic.
The Populator gem will allow you to do something close to what Factory_bot does in test environment: you'll set the data that will be provided, and the gem will automatically create several instances of your model to populate. If you only use Populator, you'll have to hardcode the content provided - not cool.
That's where Faker comes in. It has a huge array of fake content that is available to you. It can generate names, emails, credit card numbers, addresses, you name it. It randomly returns one every time it is called.
So, to the steps.
Go to your Gemfile, and make it like this:
group :development, :test do
gem 'faker'
gem 'populator'
end
Run in your terminal:
bundle install
Go to your lib folder. You'll have to do some patching in Populator gem if you use Rails version after 5.1. Inside the lib folder, create a file called populator_fix.rb. Copy the following code and paste inside it:
module Populator
# Builds multiple Populator::Record instances and saves them to the database
class Factory
def rows_sql_arr
@records.map do |record|
quoted_attributes = record.attribute_values.map { |v| @model_class.connection.quote(v) }
"(#{quoted_attributes.join(', ')})"
end
end
end
end
Save it.
Go to your seeds.rb file, and require this patch. On the first line, add the following:
require_relative '../lib/populator_fix.rb'
That's it. Your gems are set, let's do some code!
The Populate gem works like this. In the seeds.rb file, after the require, you'll call the model and pass a method called populate. You say how many instances you'd like to create, and inside the block you pass the data for the variables of your instances. Too abstract? Let's see some examples:
You have a User model with the columns 'name' and 'email'. You could populate your database like this, using Rails console:
irb(main):001:0> User.new(name:'Abraham',email:'[email protected]')
And then save it. Ok for one. But what about 10? What about 100? You probably tried creating several instances in you projects manually just to almost die of boredom. Let's solve that.
Inside the seeds.rb file, write like this:
User.populate 10 do |u|
u.name = Faker::Name.first_name
u.email = Faker::Internet.emwail
end
Let's explain this code. Write the name of the model you're calling, followed by the method populate. Tell how many times you want to spin this loop. For each loop you are creating a new user, represented by the 'u' letter (you can name it whatever you want). Inside the block, you call the new instance (u) and the variable you want to fill. You could do like u.name = 'Abraham', and u.email = '[email protected]', but that would only create 10 'Abraham's, all with the same email. If you want your database to be filled with several different and real looking instances, you'll have to use Faker.
Faker is a bless. You want to create a model of Food and create a hundred several instances, each with a different type of food? You don't have to go search for a list of food names and manually assign them. Just provide it inside the populate command:
Food.populate 100 do |f|
f.name = Faker::Food.dish
end
Check the Faker documentation to see all the potential. It's amazing.
After you wrote all the populate commands in your seed.rb file, let's make the magic happen.
Go to your terminal and call the following command:
rails db:seed
Considering you have all your tables working properly and already migrated (remember to use "rails db:migrate" before you seed), you'll have your database populated in no time.
If you are using Rails after 5.1 you'll likely have an error if you don't use the fix for the Populator gem: NoMethodError: undefined method `sanitize' with Rails X.X.X {your version}. Check again the part of the fix; maybe you forgot to require the file inside the seeds.rb.