---
title: "Tricks and Tips for using Fixtures effectively in Rails"
description: "Tricks and Tips for using Fixtures effectively in Rails"
canonical_url: "https://www.bigbinary.com/blog/tricks-and-tips-for-using-fixtures-in-rails"
markdown_url: "https://www.bigbinary.com/blog/tricks-and-tips-for-using-fixtures-in-rails.md"
---

# Tricks and Tips for using Fixtures effectively in Rails

Tricks and Tips for using Fixtures effectively in Rails

- Author: Prathamesh Sonpatki
- Published: September 21, 2014
- Categories: Rails

Recently I gave a talk at [RubyKaigi 2014](http://rubykaigi.org/2014) about
Rails fixtures. In this blog post I will be discussing some of the tips and
tricks for using fixtures effectively.

\_You can also the see the video of this talk

<iframe
  width="100%"
  height="315"
  src="https://www.youtube.com/embed/AFDwI1oIgxk"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
></iframe>

## Don't use ids.. unless required

In fixtures, we can specify id of a fixture.

```yaml
john:
  id: 1
  email: john@example.com
```

I would recommend not to specify the id. Rails generates the id automatically if
we don't explicitly specify it. Moreover there are a few more advantages of not
specifying the id.

## Stable ids for every fixture.

Rails will generate the id based on key name. It will ensure that the id is
unique for every fixture. It can also generate ids for uuid primary keys.

## Labeled references for associations like belongs_to, has_many.

Lets say we have a users table. And a user has many cars.

Car `ferrari` belongs to `john`. So we have mentioned `user_id` as 1.

```yaml
ferrari:
  name: ferrari
  make: 2014
  user_id: 1
```

When I'm looking at `cars.yml` I see `user_id` as 1. But now I to lookup to see
which user has id as 1.

Here is another implementation.

```yaml
john:
  name: john
  email: john@example.com

ferrari:
  name: ferrari
  make: 2014
  user: john
```

Notice that I no longer specify `user_id` for John. I have mentioned `name`. And
now I can reference that name in `cars.yml` to mention that `ferrari` belongs to
`john`.

## How to set a value to nil from fixture

Let's say that I have a boolean column which is `false` by default. But for an
edge case, I want it to be nil. I can obviously mutate the data generated by
fixture before testing. However I can achieve this in fixtures also.

## Specify null to make the value nil

```ruby

require 'yaml'
YAML.load "--- \n:private: null\n")
=> {:private=>nil}

```

As you can see above if the value is `null` then YAML will treat it as `nil`.

```yaml
john:
  name: john
  email: john@example.com
  private: null
```

## Leave the value blank to make the value nil

```ruby

require 'yaml'
YAML.load "--- \n:private: \n")
=> {:private=>nil}

```

As you can see above if the value is blank then YAML will treat it as `nil`.

```yaml
john:
  name: john
  email: john@example.com
  private:
```

## When model name and table name does not match

Generally in Rails, the model name and table name follow a strict convention.
`Post` model will have table name `posts`. Using this convention, the fixture
file for `Post` models is obviously `fixtures/posts.yml`.

But sometimes models do not match directly with the table name. This could be
because of legacy reason or because of namespacing of models. In such cases
automatic detection of fixture files becomes difficult.

Rails provides `set_fixture_class` method for this purpose. This is a class
method which accepts a hash where key should be name of the fixture or relative
path to fixture file and value should be model class.

I can use this method inside `test_helper.rb` in any class inheriting from
`ActiveSupport::TestCase`.

```ruby

# test_helper.rb
class ActiveSupport::TestCase

  # table name is "morning_appts". It is being mapped to model "MorningAppointment".
  self.set_fixture_class morning_appts: MorningAppointment

  # in this case fixture is namespaced
  self.set_fixture_class '/legacy/users' => User

  # in this case the model is namespaced.
  self.set_fixture_class outdoor_games: Legacy::OutdoorGame
end

```

## values interpolation using \$LABEL

Rails provides many ways to keep our fixtures DRY. Label interpolation is one of
them. It allows the use of key of fixture as a value in the fixture. For
example:

```yaml
john:
  name: john
  email: john@example.com
```

becomes:

```yaml
john:
  name: $LABEL
  email: john@example.com
```

$LABEL is not a global variable here. Its just a placeholder.
$LABEL is replaced
by the key of the fixture. And as discussed earlier the key of the fixture in
this case is `john`. So \$LABLE has value `john`.

Before [this PR](https://github.com/rails/rails/pull/14399), I could only use
this feature if the value is exactly \$LABEL. So if the email is
`john@example.com` I could not use the `$LABEL@example.com`. But after this PR,
I can \$LABEL anywhere in the string, and Rails will replace it with the key.

So the earlier example becomes:

```yaml
john:
  name: $LABEL
  email: $LABEL@example.com
```

## YAML defaults

I use YAML defaults in database.yml for drying it up and keeping common
configuration at one place.

```yaml
defaults: &defaults
  adapter: postgresql
  encoding: utf8
  pool: 5
  host: localhost
  password:

development:
  <<: *defaults
  database: wheel_development

test:
  <<: *defaults
  database: wheel_test

production:
  <<: *defaults
  database: wheel_production
```

I can use it for drying up fixtures too for extracting common part in our
fixtures.

```yaml
DEFAULTS: &DEFAULTS
  company: BigBinary
  website: bigbinary.com
  blog: blog.bigbinary.com

john:
  <<: *DEFAULTS
  name: John Smith
  email: john@bigbinary.com

prathamesh:
  <<: *DEFAULTS
  name: Prathamesh Sonpatki
  email: prathamesh@bigbinary.com
```

Note the usage of key `DEFAULTS` for defining default fixture. Rails will
automatically ignore any fixture with key `DEFAULTS`.

If we use any other key then a record with that key will also get inserted in
the database.

## Database specific tricks

Fixtures bypass the normal Active Record object creation process. After reading
them from YAML file, they are inserted into database directly using insert
query. So they skip callbacks and validations check. This also has an
interesting side-effect which can be used for drying up fixtures.

Suppose we have fixture with timestamp:

```yaml
john:
  name: John Smith
  email: john@example.com
  last_active_at: <%= Time.now %>
```

If I are using PostgreSQL, I can replace the `last_active_at` value with `now`:

```yaml
john:
  name: John Smith
  email: john@example.com
  last_active_at: now
```

`now` is not a keyword here. It is just a string. The actual query looks like
this:

```sql

INSERT INTO "users"
("name", "email", "last_active_at", "id")
VALUES
('John Smith', 'john@example.com', 'now',1144934)

```

So the value for `last_active_at` is still just `now` when the query is
executed.

The magic starts as PostgreSQL starts reading the values. `now` is a shorthand
for the current timestamp . As soon as Postgres reads it, it replaces `now` with
the current timestamp and the column `last_active_at` gets populated with
current timestamp.

I can also use the `now()` function instead of just `now`.

This function is available in
[PostgreSQL](http://www.postgresql.org/docs/9.3/static/datatype-datetime.html#AEN5861)
as well as
[MySQL](http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_now).
So the usage of `now()` works in both of these databases.

## Links

- [Human page](https://www.bigbinary.com/blog/tricks-and-tips-for-using-fixtures-in-rails)
