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