Database-driven applications often need data pre-seeded into the system, such as locations or user roles. For a long time there was no good way to do this in Ruby on Rails — the primary options were seeding data directly in migrations, having migrations call a rake task to manage the relevant records, or using an external plugin.
Rails 2.3.4 largely fixed this with the introduction of the
db/seeds.rb file and corresponding rake db:seed task. The default
seeds.rb included with a fresh Rails install offers the following examples:
cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
Mayor.create(:name => 'Daley', :city => cities.first)
Rather than scattering the seeds around dozens of files and dealing with the corresponding gotchas, there’s a single, well-known place.
seeds.rb is a wonderful thing, provided nobody ever edits it, or you’re
happy resetting your database every time it is edited — otherwise it’ll
blindly try to recreate records every time it’s run, regardless of whether the
data is already in the database. Naturally, this becomes a significant
annoyance in development.
After a couple months of wondering how my coworkers and I could update the seeds file while avoiding frequent resets, I think I’ve got a straightforward solution: replace calls like
User.create(:email => "jsmith@example.com", :name => "Jane Smith")
User.create(:email => "jsmythe@example.org", :name => "John Smythe")
with
[
{ :email => "jsmith@example.com", :name => "Jane Smith" },
{ :email => "jsmythe@example.org", :name => "John Smythe" }
].each do |user|
User.find_or_create_by_email(user)
end
(via MetaFilter)
Recently rewatched The Darjeeling Limited.
See also: ‘Waltzinblack’; The Gospel According to the Meninblack.