Rails: Unit Testing Rails Single-Table Inheritance Models

I recently spent not an insignificant amount of time trying to get my unit tests to comply with Rails' single-table inheritance. Single table inheritance allows you to map a hierarchy of classes to a single table in the database, so from one user table I can have an Employee and a Manager. They both inherit from a User model in Rails, and are stored in the users database table. A manager, though, might have more properties (fields) and methods than an Employee, which can be defined in manager.rb:

class User < ActiveRecord::Base

  validates_presence_of :name


# manager.rb

class Manager < User

  has_many :employees, :foreign_key => :user_id

  def grant_payrise(employee, amount = 100)

    employee.pay += amount



# employee.rb

class Employee < User

  belongs_to :manager, :foreign_key => :user_id

  def ask_for_payrise




In the code above, both employees and managers are stored in the users table from which they inherit. However, Rails will recognise which users are managers and which are employees from clever use of a reserved string field on the users table called type. The type field stores which class of user a record represents, and Rails' finders will automatically recognise that field. This means your controller can call:

[email protected] = Employee.find(:all)```

That code will only return users who are employees, and return them as Employee objects.

Unit Testing

My problem occurred when I tried to update my unit tests to cope with single-table inheritance. To keep things tidy, and separate my employee tests from my manager tests, I moved all my employee testing into test/units/employee_test.rb and my employee fixtures into test/units/employees.yml, and did the same for managers. When I ran the tests with a rake test:units, though, I was greeted with pages of SQL errors.

It turns out that you need to define all your fixtures to the root object (or direct descendent of ActiveRecord::Base), in my case the User class. So your tests for both employees and managers should still be placed in test/units/usertest.rb_ and the fixtures in test/units/fixtures.rb, e.g:

```ruby# users.yml


first_name: Joe

last_name: Bloggs

type: Manager # Note the type field must match the ActiveRecord


first_name: Joe

last_name: Bloggs

type: Employee # Note the type field must match the ActiveRecord class.


first_name: John

last_name: Stone

type: User```

In hindsight, this makes sense, but after some thorough research (read: Google), I couldn't find much - if anything - on unit testing single-table inheritance models, so thought I'd post a note to help anyone else in this situation.