You are currently browsing the monthly archive for December 2007.

This last summer I finished the joinfix gem providing a solution to the fixture join problem — mainly that it’s a pain to create fixtures by specifying entry ids across multiple fixture files. When Mike Clark and Chad Fowler opened up submissions for Advanced Rails Recipies, I sent JoinFix to them and it was accepted.

I took a look at the new Foxy Fixtures in Rails 2.0 and was shocked/pleased to find something similar has gotten incorporated directly into the core. Goes to show how problematic fixtures really were. JoinFix still is interesting, however, mainly because JoinFix lets you define entries inline.

Consider the following data model:

  class User < ActiveRecord::Base  has_many :user_groups
    has_many :groups, :through => :user_groups
  end

  class Group < ActiveRecord::Base
    has_many :user_groups
    has_many :users, :through => :user_groups
  end

  class UserGroup < ActiveRecord::Base
    belongs_to :user
    belongs_to :group
  end

You can write your fixtures using the naming scheme you lay out in your models, referencing entries across multiple fixture files (similar to Foxy) or you can define them inline:

   [users.yml]
   john_doe:
     full_name: John Doe
     groups: admin_group   # => reference to the 'admin_group' entry

   jane_doe:
     full_name: Jane Doe
     groups:               # => you can specify an array of entries if needed
       - admin_group
       - worker_group:     # => inline definition of the 'worker_group' entry
           name: Workers

   [groups.yml]
   admin_group:            # => the referenced 'admin_group' entry
     id: 3                 # => you can (but don't have to) specify ids
     name: Administrators

Join entries implied in your definition, as in a has_and_belongs_to_many association, will be created and named by joining together the names of the parent and child, ordered by the ’<’ operator. For example, the users.yml and groups.yml fixtures produce these entries:

  [users]
  john_doe:
    id: 1                  # => primary keys are assigned to all entries
    full_name: John Doe
  jane_doe:
    id: 2
    full_name: Jane Doe

  [groups]
  admin_group:
    id: 3
    name: Administrators
  worker_group:
    id: 1
    name: Workers

  [user_groups]
  admin_group_john_doe
    id: 1
    user_id: 1             # => references are resolved to their foreign keys
    group_id: 3            # => explicitly set primary keys are respected
  admin_group_jane_doe
    id: 2
    user_id: 2
    group_id: 3
  jane_doe_worker_group    # => Notice the '<' operator in action
    id: 3
    user_id: 2
    group_id: 1

Nesting is allowed. This will make the same entries as above:

  [users.yml]
  john_doe:
    full_name: John Doe
    groups:
      admin_group:
        id: 3
        name: Administrators
        users:
          jane_doe:
            full_name: Jane Doe
            groups:
              worker_group:
                name: Workers

In this final form, JoinFix defines a highly-involved fixture in one chunk, in one file. This can be a BIG advantage when you try to test some cross-table, complicated lookup. The full fixture is centralized and easy to manage.

Follow

Get every new post delivered to your Inbox.