What is sprig?

It's a ruby gem for adding seed/sample data to your Rails applications.

Sprig was created by ltk & fosome at Viget when other seeding tools failed to handle the sample data needs of an in-development social network. Because of its origins, sprig excels where other tools fall short: handling large amounts of related data in real-world Rails apps.


Seed by Convention

Treat your data like data, not code. Sprig's seeding engine builds seed records from data stored in common formats.

With Sprig

Store your seed data in a proper data format.

Yaml

records:
  - sprig_id:       jane
    first_name:     Jane
    last_name:      Doe
    age:            25
    favorite_color: blue
  - sprig_id:       john
    first_name:     John
    last_name:      Smith
    age:            34
    favorite_color: green

JSON

{
  "records": [
    {
      "sprig_id": "jane",
      "first_name": "Jane",
      "last_name": "Doe",
      "age": 25,
      "favorite_color": "blue"
    },
    {
      "sprig_id": "john",
      "first_name": "John",
      "last_name": "Smith",
      "age": 34,
      "favorite_color": "green"
    },
  ]
}

CSV

sprig_id,first_name,last_name,age,favorite_color
jane,Jane,Doe,25,blue
john,John,Smith,34,green

Without Sprig

Obscure your data with code. Works fine for a few records. Not so much for a few thousand.

User.create(first_name: 'Jane', last_name: 'Doe', age: 25, favorite_color: 'blue')
User.create(first_name: 'John', last_name: 'Smith', age: 34, favorite_color: 'green')

Relational Seeding

Easy seed data relationships? You better believe it.

Without Sprig

Step 1:

Solve the insert-order puzzle.

Step 2:

zip_code_1 = ZipCode.create(code: '22046')
address_1 = Address.create(zip_code: zip_code_1)
user_1 = User.create(name: 'John', address: address_1)
zip_code_2 = ZipCode.create(code: '22202')
address_2 = Address.create(zip_code: zip_code_2)
school_1 = School.create(address: address_2, principal: user_1)
address_3 = Address.create(zip_code: zip_code_2)
school_2 = School.create(address: address_3)

Step 3:

Tears and beers.

With Sprig

Insert-order is handled for you.

Seed records act like persisted records and are accessible anywhere.

You just focus on your data, not on how to insert it.

# users.yml
records:
  - sprig_id: 1
    name: John
    address_id: <%= sprig_record(Address, 1).id %>

# addresses.yml
records:
  - sprig_id: 1
    zip_code_id: <%= sprig_record(ZipCode, 1).id %>
  - sprig_id: 2
    zip_code_id: <%= sprig_record(ZipCode, 2).id %>
  - sprig_id: 3
    zip_code_id: <%= sprig_record(ZipCode, 2).id %>

# zip_codes.yml
records:
  - sprig_id: 1
    code: 22046
  - sprig_id: 2
    code: 22202

# schools.yml
records:
  - sprig_id: 1
    address_id:  <%= sprig_record(Address, 2).id %>
  - sprig_id: 2
    address_id:  <%= sprig_record(Address, 3).id %>

Environment Specificity

Add everything you could want in :development, and only what you need in :production.

Production

/db/seeds/production.rb

include Sprig::Helpers

sprig [ZipCode]

/db/seeds/production/zip_codes.yml

# All the zip_codes

Development

/db/seeds/development.rb

include Sprig::Helpers

sprig [User, Widget, ZipCode]

/db/seeds/development/zip_codes.yml

# A few zip codes

/db/seeds/development/users.yml

# A few fake users

/db/seeds/development/widgets.yml

# A few fake widgets

Flexible + Customizable

All the power you want, with the flexibility you need.

Customize Datasources

Can't stand naming conventions? Okay... no problemo. Point sprig at any file you want.

fanciness = {
  :class  => User,
  :source => open('https://spreadsheets.google.com/feeds/list/somerandomtoken/1/public/values?alt=json'),
  :parser => Sprig::Data::Parser::GoogleSpreadsheetJson
}

sprig [
  fanciness,
  Post,
  Comment
]

Add a Custom Data Parser

Sometimes Yaml, JSON, and CSV formats just don't cut it. Sprig might not understand your whacky data format out of the box, but it's a quick learner. You can even parse Google Spreadsheets with ease.

Teach sprig new tricks by defining your own custom parser classes inheriting from Sprig::Parser::Base. Then simply define a #parse method that returns a hash of your record data in the following format.

{
  records: [
    {
      some_attribute: 'some_value',
      another_attribute: 'some_other_value'
    }
  ]
}

Plain Old Ruby

Sprig is only activated when and where you want it within a plain old ruby file. Since sprig doesn't employ an all-or-nothing approach, you're always free to handle what Sprig can't.

/db/seeds/development.rb

# Your awesome code goes here.

include Sprig::Helpers
sprig [User, Widget, ZipCode]

# More of your awesome code goes here.

License

MIT license for great justice.