Planting the seeds
27 comments Latest by abercrombie clothes Thu, 18 Mar 2010 06:07:17 GMT
Yesterday, the Rails team released 2.3.4, which includes standardized way for loading seed data into your application so that you didn’t have to clutter your database migrations.
I noticed a few comments on some blogs where people were asking how to use this new feature, so here is a quick runthrough a few ways that you can use it.
Populating Seed Data Approaches
The db/seeds.rb file is your playground. We’ve been evolving our seed file on a new project and it’s been great at allowing us to populate a really large data. Here are a few approaches that we’ve taken to diversify our data so that when we’re working on UI, we can have some diversified content.
Basic example
Any code that add to db/seeds.rb is going to executed when you run rake db:seed. You can do something as simple as:
# db/seeds.rb
Article.create(:title => 'My article title', :body => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit')Just create database records like you would in your Rails application or in script/console. Simple enough, right? Let’s play with a few other approaches that we’ve begun to use.
Use the names of real people
We’re using the Octopi gem to connect to github, collect all the names of people that follow me there, and using their names to seed our development database.
@robby_on_github = Octopi::User.find('robbyrussell')
# add a bunch of semi-real users
@robby_on_github.followers.each do |follower|
github_person = Octopi::User.find(follower)
next if github_person.name.nil?
# split their name in half... good enough (like the goonies)
first_name = github_person.name.split(' ')[0]
last_name = github_person.name.split(' ')[1]
new_person = Person.create(:first_name => first_name, :last_name => last_name, :email => Faker::Internet.email,
:password => 'secret', :password_confirmation => 'secret',
:github_username => follower, :website_url => github_person.blog)
# ...
endWe do this with a few sources (twitter, github, etc..) to pull in the names of real people. If you want to be part of my seed data, you might consider following me on Github. ;-)
Use Faker for Fake data
You may have noticed in the previous code sample, that I used Faker in that code. We are using this a bunch in our seed data file. With Faker, you can generate a ton of fake data really easy.
person.links.create(:title => Faker::Lorem.words(rand(7)+1).join(' ').capitalize,
:url => "http://#{Faker::Internet.domain_name}/",
:description => Faker::Lorem.sentences(rand(4)+1).join(' '))We might toss something like that into a method so that we can do the following:
@people = Person.find(:all)
500.times do
generate_link_for(@people.sort_by{rand}[0])
end...and we’ll get 500 links added randomly across all of the people we added to our system. You can get fairly creative here.
For example, we might even wanted random amounts of comments added to our links.
def generate_link_for(person)
link = person.links.create(:title => Faker::Lorem.words(rand(7)+1).join(' ').capitalize,
:url => "http://#{Faker::Internet.domain_name}/",
:description => Faker::Lorem.sentences(rand(4)+1).join(' '))
# let's randomly add some comments...
if link.valid?
rand(5).times do
link.comments.create(:person_id => @people.sort_by{rand}[0].id,
:body => Faker::Lorem.paragraph(rand(3)+1))
end
end
endIt’s not beautiful, but it gets the job done. It makes navigating around the application really easy so that we aren’t having to constantly input new data all the time. As mentioned, it really helps when we’re working on the UI.
Your ideas?
We’re trying a handful of various approaches to seed our database. If you have some fun ways of populating your development database with data, we’d love to hear about it.
Enjoying the content? Be sure to subscribe to my RSS feed.






It’s 2.3.4.
Tom, thanks for pointing that out. Fixed!
I’ve generally just used rake to populate my database… pretty much copied Ryan Bates’ railscast: http://railscasts.com/episodes/126-populating-a-database
Sadly, somebody botched this release! There are various major issues with Ruby 1.9.1 computability!
Im on the “rake away”. It gave us grained control over the populate process.
task :setup=>[ “db:drop”, “db:create”, “db:migrate”, “bootstrap:permissions”, “bootstrap:groups”]
To populate data for testing in development I’ve been using a rake task that pulls in the same factory_girl factories I use in my tests. I use Faker in those factories to generate random data.
I use Mocha for stubbing in tests, no fixtures! :-) I guess there are sometimes a couple “create_blah” macros in there too.
In production and development: seed_fu. There were some problems scaling it, but I’ve released updates in a fork:
Seed_fu can read .gz now, generate seeds from code, and it doesn’t eat all your memory. We use it for seeding over a million rows. It’s also way faster than before.
I use the same technique as Nathan above, but use Machinist + Faker. That way I can just require machinst and my existing blueprints file and just do something like:
20.times { Person.make }
It feels like this is a violation of intentions. It was my understanding that the `db:seed` task should be used for initial values needed for the application to function properly. For example, this might be used to set the default set of allowed subscription plans or fill a zip_codes table.
It seems that a better convention for fake/dummy data would be to put that under a `db:populate` task (or similar).
require 'active_record/fixtures fixtures_dir = 'db/fixtures' Dir.glob("#{RAILS_ROOT}/#{fixtures_dir}/*.yml").each do |file| Fixtures.create_fixtures(fixtures_dir, File.basename(file, '.*')) endI think of seed data the same way as Ryan mentions above. In that vein perhaps adding a require to the spec or test helper would be a good idea to make sure your test database is also seeded correctly with the required data.
Hey, what a nice way to use Octopi! Me likey! :)
+1 to Ryan’s comment. This is solid example of populating sample/demo data, but seed data should be reserved for the minimal set of data required for your app to function.
A good home for this sample/demo data might be
db/samples.rbordb/demo.rb(with a corresponding rake task ofrake db:samples).Is it only me that thinks this new seeding feature is a sloppy/half-hearted try on the seeding problem? This new feature didn’t affect my pulse at all, and won’t. Use the non-sloppy solution “Bootstrapper” (and Machinist + Forgery) instead…
http://github.com/sevenwire/bootstrapper
To behonest this Rails seeding feature chocked me a bit, as Rails ususally is quivalent to awesomeness. =o
@grimen: I don’t get what bootstrapper does which this doesn’t: you can just switch on RAILS_ENV in seeds.rb if you need different data based on environment.
Agreed with others that seeds should be for initial seed data, not demo data. (For records such as groups, categories, regions, etc.)
@Andrew Vit: Well, the Rails seeds feature I could rough-implement in 2 minutes myself, so I don’t see the point of it at all. I know that, and that is the point – what is this seed feature really adding? Bootstrapper is a nice DSL, and adds a few loading helpers – way better than this I’m afraid.
I use db:bootstrap (and db:bootstrap:reset) no matter I’m in development, staging, or production – easy and clean. I also can specify certain bootstrapper (a bootstrapper is either an environment, or something else identified by a name) if I don’t want to run all current environment bootstrappers, or got a non-standard bootstrapper for cetain type of situations, i.e. load completely different data. Sky is the limit – with less configuration/code.
...and code says more than hundred words:
http://pastie.org/615391
While I can appreciate Seeds and FixtureReplacement, I’ve found out of experience (on a few big projects) that the yml files are easier to maintain and deal with.
With yml, if I want to create a user for test, I just add the fields and values in the yml. With Seeds and the like, I have to type more.
One of the things I like about Rails/Ruby was terseness. To me, Seeds is not terse enough and it’s a step in the opposite direction. I think this is just a solution looking for a problem.
Created a plugin to extend model and scaffold generators to create individual seeds files for models and extended db:seed so that it can rake individual seeds.
http://github.com/markwfoster/seeded-generation
Then you can implement all these ideas, including using separate files to store the data and get away from migrating fixtures, etc., using the new seeds.rb functionality.
Many people discount ugg cardy boots would regard these Boots as “unfashionable” or “uncool” because the boots look discount ugg boots big and odd. Some have even called for a boycott on wearing these boots due to their distaste for its look. Despite all of this, the Ugg Boots has wholesale ugg boots been enormously successful and is probably here to stay
Ruby is on Rails?!
Kewl ;O
nike shox ghd hair straightener china wholesale
It feels like this is a violation of intentions. It was my understanding that the `db:seed` task should be used for initial values needed for the application to function properly. For example, this might be used to set the default set of allowed subscription plans or fill a zip_codes table.
It’s not beautiful, but it gets the job done. It makes navigating around the application really easy so that we aren’t having to constantly input new data all the time.
Great information ! Thanks much. Planting the seeds will give the fruit for sure
thank you