asplake

Saturday, December 31, 2005

STI followup: unit tests

I'm a complete newbie when it comes to unit testing in Ruby (I started only today), but here's a unit test for yesterday's STI example.

Test data (in test/fixtures/element_defs.yml) below. Note that the first entry root_name_def is subclassed to RefComponentDef.

  root_name_def:
    type: RefComponentDef
    id: 1
  root_description_def:
    id: 2

In my tests for the parent class ElementDef it looks like I'm disregard subclassing altogether, but passing this test shows implicitly that subclasses and their objects load fine together:

  class ElementDefTest < Test::Unit::TestCase
    fixtures :element_defs
  
    # Check that the fixture data makes sense
    def test_fixtures
      assert_kind_of ElementDef, element_defs(:root_name_def)
      assert_kind_of ElementDef, element_defs(:root_description_def)
   end
  
    # Check that the loaded data makes sense
    def test_loaded_data
      assert_kind_of ElementDef, ElementDef.find_by_id(element_defs(:root_name_def)[:id])
      assert_kind_of ElementDef, ElementDef.find_by_id(element_defs(:root_description_def)[:id])
    end
 

In the subclass's tests I show that its objects can be read via the superclass's find methods:

  class RefComponentDefTest < Test::Unit::TestCase
    fixtures :element_defs

    # Check the ElementDef fixture data correctly identifies :root_name_def as a RefComponentDef
    def test_fixtures
      assert_kind_of RefComponentDef, element_defs(:root_name_def)
    end
  
    # Check that a RefComponentDef can be read back from the database via its superclass
    def test_loaded_data
       assert_kind_of RefComponentDef, ElementDef.find_by_id(element_defs(:root_name_def)[:id])
    end
  end
I could add this to the wiki - did anyone find this useful?

Technorati tag:

Friday, December 30, 2005

Loading model classes with STI

I found out the hard way that the SQL generated by Single Table Inheritance (STI) depends on what Rails knows to be the subclasses of the class you attempt to query. If the subclasses don't happen to be loaded, the query doesn't return all the results you'd expect. The simple cure is to add dependencies in your ApplicationController. You can do this more than once, eg:
  class ApplicationController < ActionController::Base
    # Make sure that ActiveRecord is always aware of Entry's subclasses
    model :entry, :catalog, :root_catalog

    # Make sure that ActiveRecord is always aware of ElementDef's subclasses
    model :element_def, :ref_component_def
  end
Spookily, having decided to write this up here and (later tonight) on the Rails wiki at WhenToUseTheModelMethod, I see this raised as a bug today. See ticket 3358. Personally, I think this is a feature rather than a bug, but I suppose it is slightly weird that a superclass should be dependent on its subclasses. Technorati tag:

Tuesday, December 20, 2005

Here goes...

...because I want to write something non-boilerplate in Rails, and the world clearly needs another Content Management System ;-) I'll post the odd tip or trick here as I go.