Smarter Rails Seeding with Sprig
Lawson Kurtz, Former Senior Developer
Article Category:
Posted on
We love writing Rails apps at Viget. The framework covers so much ground right out of the box by convention. However, Rails is oddly silent about one thing: seed data. Beyond a simple Rake task, db:seed
, each project is left on its own to define how best to provide seeds.
Your Seed Data Is Important
Without expounding too much on why seeds are vital over the lifetime of a project, we use them to provide:
- data that's required for the app to function properly (admin accounts, roles, etc)
- sample data so staging environments can feel like the real thing
- data in a variety of potentially intricate states
- a backdrop for QA testing
- a reproducible "vanilla" integration server state
Given the many uses across the whole team, we saw a chance to create a standard for our own process. From that effort grew (oh ho!) Sprig.
Introducing Sprig
Seed by Convention
Sprig provides common sense conventions for seeding Rails apps. The simplest use might look like:
Step 1:
db/seeds/development/users.yml
records:
- sprig_id: 1
first_name: "John"
last_name: "Smith"
date_of_birth: "<%= 1.year.ago %>"
You define your seeds in the formats you love: YML, JSON, and CSV are supported out of the box.
Step 2:
db/seeds/development.rb
include Sprig::Helpers
sprig User
You tell Sprig which classes should be seeded for the current environment. Sprig finds your lovely seed files and does the rest.
Step 3:
No wait... That's it.
Relational Seeding for Relational Data
All real-world applications contain relationships between models. Sprig allows seeds to reference one another as if they already exist, so seeding relationships is as easy as seeding records.
records:
- sprig_id: 1
user_id: "<%= sprig_record(User, 1).id %>"
body: "Ipsum lorem"
Keeping track of the order and direction of your seeds' dependencies can be tricky. No worries. Sprig automatically determines the order with which seeds should be persisted. And if you accidently create a circular dependency, Sprig helps you resolve it.
Customization
Although the Sprig convention expects YML, CSV, and JSON seed files, it doesn't limit you to them. You can easily create and use your own custom parser (like this one that lets us use a Google Spreadsheet as our data source). Sprig can be extended to parse any kind of seed file from any source:
sprig [{
class: Post,
source: open('https://spreadsheets.google.com/feeds/list/somerandomtoken/1/public/values?alt=json'),
parser: Sprig::Data::Parser::GoogleSpreadsheetJson
}]
Sprig also accepts options like find_existing_by
which tells Sprig to update records matching provided criteria instead of persisting a new record, allowing for idempotent seeding operations.
Give It A Spin
The full set of features can be found on the Sprig pages. We've already used Sprig on many of our own projects for great justice and hopefully you can too!
So what are you waiting for? gem install sprig
To Improve Is To Change
Something missing? We're actively developing Sprig to be better all the time and are happily accepting issues and pull requests at the project's home on GitHub.
Thanks to Ryan Foster for his significant contributions to this post and the Sprig project, to the entire Viget development team for helping to make Sprig awesome, and to Mindy Wagner for the sweet logo.