Seeding a Rails Development Environment with Test Fixtures
Posted on January 13, 2020
I’m a big fan of doing things The Rails Way.
erb as the templating language.
minitest instead of reaching for
Using ActiveRecord fixtures instead of employing the
This is not an indictment of the alternative solutions. They have their place, and competition drives innovation. But I’ve found leaning hard into convention over configuration has continued to pay dividends, so I’m going to keep investing.
ActiveRecord fixtures are typically associated with testing.
But there’s a command to load them into any environment...
RAILS_ENV=development bin/rails db:fixtures:load
This will take the test data and shove it into the development environment.
The Rails convention for loading default data into the environment is
This command loads the environment, and executes the file
I like the ideal of
bin/rails db:seed being a command you run one time when setting up a project.
If it’s ever being invoked again, it means that I’m wanting to start over from ground zero.
Building on this opinion of the world, this is what a typical
db/seeds.rb file looks like in one of my Rails projects.
# db/seeds.rb def load_fixtures Rake::Task["db:fixtures:load"].invoke end def confirmed? return true if ENV["CONFIRM_FIXTURE_LOAD"] puts <<~EXPLAIN ERROR! Loading fixtures into the database will clobber all existing data in the tables. To confirm this is what you want to do, set the environment variable CONFIRM_FIXTURE_LOAD $ CONFIRM_FIXTURE_LOAD=yeppers bin/rails db:seed EXPLAIN false end load_fixtures if confirmed?
Now you can have your cake and eat it to. Where your cake is your test environment. And eating it is your development environment.
I like this for a few reasons.
- Loading fixtures is fast. Like, wicked fast.
- With a great upside of speed, comes the great downside of blowing away any data you might care about. Where the raw
bin/rails db:fixture:loadlacks, wrapping it with confirmation communicates the downside to the future self.
- It captures the opinion that
bin/rails db:seedshould be for setting up a project, not migrating over time.
- It’s sure to work. If the tests are passing, the fixtures are loading into the test database, which means they’ll load into the development environment too.
There is a downside.
YAML can be a real pain point when dealing with lots of data, complex associations, join tables, etc. I’ve got some strategies for overcoming that downside, but that’s another post.