Beginners Level

Best practices using Rails Seeds


Reading Time: 2 minutes

Best practices using Rails Seeds

Rails seeds are useful since they help us populate the test and development DBs with data; this means that we can simply run rails db:seed for rails 5 and beyond or rake db:seed for rails 4 and prior and have the app up and running with enough information to be productive right away. Rails documentation has a pretty good definition for the seeds, and here you have it :

To add initial data after a database is created, Rails has a built-in
'seeds' feature that makes the process quick and easy. This is
especially useful when reloading the database frequently in development
and test environments. It is easy to get started with this feature: just
fill up db/seeds.rb with some Ruby code, and run rails db:seed

Best practices

Break them into smaller files

By default, rails encourages you to put the logic of the initial data creation inside the db/seed.rb file, but over the time that file could become huge and complex; One solution to prevent this from happening is to create a file per model or group of data and then load them into the seed.rb, for example, let’s suppose we have a web page to manage doctors appointments, in that case, we would have next models User, Roles and Appointment.

So we create a new seeds folder inside the rails db folder to store the following 3 seed files with the following names: app/db/seeds/001_roles.rb, app/db/seeds/002_users.rb and app/db/seeds/003_appointments.rb we create them with that naming convention to be able to control the loading order of the seeds; this is helpful when we have models that depend on the data created by other models like Appointment that needs a doctor and a patient to exist or the users that need roles to be identified within the app. Once we create our seeds files, we can load them into the seed.rb file with the following code:

Dir[Rails.root.join('db/seeds/*.rb')].sort.each do |file|
puts "Processing #{file.split('/').last}"
require file
end

Unique records

For some devs, it is common to run the seeds command (rails db:migrate or rake db:migrate) because sometimes they forget if they have already run them and other times because they have edited a seed file (which should not be a problem nor create data duplication) which is easily fixed by adding the seeds data using the rails methods find_or_create_by. Following the appointments app example we would do something like this:
app/db/seeds/001_roles.rb

Role.find_or_create_by(name: ‘Patient’) do |patient|
Patient.availability = ‘8-5’
end
Role.find_or_create_by(name: ‘Doctor’)

app/db/seeds/002_users.rb

patient_role = Role.find_by_name(‘Patient’)
doctor_role = Role.find_by_name(‘Doctor’)

User.find_or_create_by(first_name: ‘John’, last_name: ‘Doe’, role: patient_role)
User.find_or_create_by(first_name: ‘Janne’, last_name: ‘Doe’, role: doctor_role)

By saving the records like that, we can avoid duplicating the data that we already have in the DB (if any). You could try something a little bit different if you like/need to do so, nevertheless, I did it this way myself 

patient_role = Role.find_by_name(‘Patient’)

User.where(first_name: ‘John’, last_name: ‘Doe’).first_or_create do |user|
user.role = patient_role
end
Development
Dragonfly: Serving Remote Content
Ruby
Rack Basics – A Rack Introduction
Rails
ActiveRecord::Observer