How To Use Fixtures to Populate Your Database in Rails
Fri, Jul 11, 2008
UPDATE: I’ve been using this method for awhile now: http://railspikes.com/2008/2/1/loading-seed-data
Seed data is data that the app is dependent on. It is data that has to exist if you were to wipe the database clean and reload your schema. Some examples would be a list of cities/states, a list of categories, or the initial ‘admin’ user account.
Most people looking at this thread want seed data rather than to populate their database with test/generated content. For the latter, you can go the route below or try Forgery
—
This is a response to the email I’ve been getting asking me how to use fixtures to load data into a database.
You want to create dummy entries in your Rails app, either for testing, for development, or for production, to make your site appear popular. Whatever the reason, populating your database can be done easily using fixtures.
While rake/fixtures/migrations can get a lot more complex, this will be a brief introductory example.
Initial App setup
$ rails characters $ cd characters/
Edit config/database.yml – We only need a development database. So open up PHPMyAdmin or the MySQL command shell and:
mysql> CREATE DATABASE characters_development; Query OK, 1 row affected (0.00 sec)
(I’m assuming you’re using MySQL. You can use anything; SQLite, Postgres, etc..)
Create a model and a table in the database (using a migration)
$ script/generate model Character exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/character.rb .... $ vim db/migrate/001_create_characters.rb
Sexy migration:
class CreateCharacters < ActiveRecord::Migration def self.up create_table :characters do |t| t.string :name, :alias, :motto t.timestamps end end def self.down drop_table :characters end end
Now migrate development (default environment):
$ rake db:migrate
Create the characters fixture
$ vim test/fixtures/characters.yml
This is a YAML file. It is easy to read and easy to edit. (One may also use the CSV format, extension .csv).
Some notes:
- Each model has a corresponding fixture file with the same name in the test/fixtures/ path in your app’s root directory.
- Each ‘fixture’ is a record in the database table, and consists of a label, and then values for each field (i.e., name, age, etc..).
- Optional fields can be skipped. They will default to either NULL, or their default value set in the database.
- The id doesn’t need to be specified. It will be auto-incremented automatically, but be careful of conflicts if you’re specifying the ID for some fixtures and not others.
- Whitespace matters. Make it purty.
- You may embed Ruby code in the fixture file, in both the YAML and CSV fixture formats. (i.e., <% f() -%> or created_at: <%= Time.now %>)
- To load fixtures, you use rake db:fixtures:load. This loads the fixtures into your current environment (can be set via RAILS_ENV shell var or in config/environment.rb).One thing that might be confusing is the fact that fixtures reside in test/. Many people believe that fixtures can only be used in the test environment, but this is not the case.
- When a fixture are loaded, any data previously in the table will be wiped out. You don’t need to fear altering or losing your test data when testing (i.e., destroy methods, …), just reload the fixtures. In the test environment, fixtures may be loaded before each test case is run by using the fixtures method (fixtures :employees, :orders, …). Keep in mind that you’re using a freshly loaded fixtures between every case method (if you’re loading).
This is what our fixture file should look like. I will dissect it below:
riddler: name: Edward Nashton alias: Riddler motto: Riddle me this, riddle me that pp: name: Peter Parker alias: Spiderman motto: One for JJ created_at: <%= Time.now %> updated_at: <%= Time.now %> JILL: id: 101 name: Jill Valentine motto: Im a member of S*T*A*R*S dan_forden: name: Dan Forden motto: Toasty! hotness: name: Sorceress motto: Time is mana Airplane: name: Steve McCroskey motto: Looks like I picked the wrong week to quit sniffing glue.
Let’s examine the first fixture:
riddler: name: Edward Nashton alias: Riddler motto: Riddle me this, riddle me that
riddler:
This is a name for the fixture. It begins at the beginning of the line, and it doesn’t matter what you call it. That information is not saved in the database and you might never use it. Ideally, names should be descriptive. You may also just go generic, “person1, person2, person3″ etc.
When using the CSV format, fixture names are generated automatically and are in this format:
model_name-counter
In our example above, our fixtures would be named character-1, character-2, etc.
name: Edward Nashton alias: Riddler motto: Riddle me this, riddle me that
These three are the values this fixture (record) will have in the database. They go under the fixture name, tabbed or spaced evenly. When going on to the next fixture, just leave a blank line.
The above is like doing this:
>> r = Character.new >> r.name = 'Edward Nashton' >> r.alias = 'Riddler' >> r.motto = 'Riddle me this, riddle me that' >> r.save
id, created_at and updated_at are optional, but may be specified. Keep in mind that this file is going to be preprocessed with Ruby, so you may embed Ruby code (ERb) anywhere in the file.
Load Fixture into Development Database
This loads fixtures into the current RAILS_ENV, which, by default, is development.
$ rake db:fixtures:load
If you check your database now, you will find the fixtures you just loaded residing in the specific table. Let’s poke at this table in the Rails console.
$ script/console >> them = Character.find(:all) => [#> them[0].name => Edward Nashton >> them[0].alias => Riddler >> them[0].motto => Riddle me this, riddle me that
See these links for more info:
External links
- Fixtures Just Got a Whole Lot Easier
- Rails Fixture Tips
- The Lo-Down on Fixtures
- Fixtures in Rails 2.0
- Migration Related Rake Commands (Rake Cheatsheet)
Why not subscribe to the feed?. If you’re on a mobile device I suggest Viigo
Tags: code, fixtures, migrations, mysql, phpunit, rails, Ruby on Rails






July 11th, 2008 at 4:59 pm
Just fyi, in Rails 2.1 you can also skip the manual database creation step by doing this:
rake db:create:all
This will create all of your local databases if they don’t exist yet (i.e. only those databases in database.yml that use localhost or 127.0.0.1 as their host name).
July 25th, 2008 at 10:03 pm
So I’ve got production data that I need in every instance of my app. The best example is a “countries” table for user selection. My take on this is to put that type of data directly in a migration. That way it lives in every instance and gets migrated appropriately.
My problem is that when I do a rake db:fixtures:load, it drops anything created in my migrations. :/ Am I doing it wrong?
J
July 28th, 2008 at 12:22 am
Hey Jamie,
rake db:fixtures:load is dropping the current records in your database (those created by the migrations) before adding its own data. This prevents duplicates from being added every time you run tests. You can keep the data in a fixture.
July 31st, 2008 at 9:35 am
Using fixtures to populate default or initial database values may cause some problem due to the way the id are generated. In fact, the id seems to be generated by calculating a hash of the fixture name.
If you use this to populate a “mutable” table (like user table for instance), you will have your sequence of id beginning to a possible (random) high value. Say if you have 1 admin user loaded from fixture with id=283156471, then all users that will be added will have consecutive id beginning at 283156472.
August 20th, 2008 at 10:40 pm
I have been using seed-fu plugin lately for handling data seeding and I’ve found it to be a nice solution. I was always uncomfortable with the idea of using my testing fixtures for seeding. The best part, besides being able to key off a field (or fields) and change existing seed data attributes in production, is that it’s all just Ruby inside, not YAML.