Ruby on Rails

Tips & Tricks with Fixtures

Fixtures have long been a great element of Ruby on Rails and I like getting the most out of them. There are lots of tools that you can tack on that might make them more shiny or do one more thing, but on their own, they do a great job and in most cases, you really don't need anything else for loading data for tests. Read on for all the basics, and also a few tips that make using them all that much easier!

Fixtures Basics

Fixtures are primarily used for loading data in support of tests. They are transactional--loaded into the test database before every test, then on the test completion, the database is rolled back to the same point prior to the test. Located in the test/fixtures directory, they are YAML files, with an object name, followed by key-value pairs of data. If you use the standard generators for models and scaffolding, corresponding model YAML files will be created reflecting all of the attributes of the model and stored with the exact model.yml name:

# YAML comment. These are my users.
one:
  email: MyString
  password: MyPassword
two
  email: MyString
  password: MyPassword

Commenting

Comments can be used, with lines beginning with a #.

Associations

For associations, fixtures can reference other fixtures, as such with this file, connected to users.yml above:

# Blog posts
one:
  title: A Blog post
  content: Some content here
  user: one

Notice you don't use user_id as the key, just user, which works since you have connected the two as Post belongs_to User.

ERB

ERB works with fixtures, such as:

<% 1000.times do |n| %>
user_<%= n %>:
  username: <%= "user#{n}" %>
  email: <%= "user#{n}@example.com" %>
<% end %>

Active Record Validations and Callbacks

When Fixtures are loaded, they bypass the normal Active Record object creation process, so validations and callbacks are not used. This is a drawback, but the reason is that it greatly speeds up the object creation process, which is necessary since usually many tests are run, with Fixtures loaded prior to every test. As result, this requires you to create all related data that would be needed in a test.

Using Fixtures in a Test

Tests will automatically load fixtures into Active Record objects:

# As a single object
users(:one)

# Calling methods on an object
users(:one).email

Loading

To manually load fixtures:

rails db:fixtures:load

That may do too much, so if you want to load specific fixtures, you do so by declaring the fixtures you want into the FIXTURES environment variable:

rake db:fixtures:load FIXTURES=states

You can also load multiple Fixtures:

rake db:fixtures:load FIXTURES=states,cities,countries

Tips

Tip 1 - Fixtures are Idempotent, reload as necessary

Fixtures can be reloaded multiple times and you won't get duplicates of the same objects.

Tip 2 - You can use Defaults

DEFAULTS: &DEFAULTS
  password: some_password

mary:
  <<: *DEFAULTS
  name: Mary
  email: mary@example.com

Tip 3 - Use $LABEL as a replacement

The label of the current fixture is always available as a column value.

johndoe:
  name: John Doe
  subdomain: $LABEL
  email: $LABEL@email.com

Tip 4 - Fixtures are unordered unless you use the OMAP YAML type:

--- !omap
- parent:
    id:         1
    parent_id:  NULL
    title:      Parent
- child:
    id:         2
    parent_id:  1
    title:      Child

Carson R Cole