Rails 3 STI Class Loading Bug In Development Mode


Using deep STI(meaning more than one level of inheritance for your STI models) with Rails 3 you might get an error ActiveRecord::RecordNotFound: when you call or refer to one of your deep level subclasses.

For example:

class Party < ActiveRecord::Base 
class Festival < Party 
class MultiEventFestival < Festival 

After running all the migrations you'll have your models and DB set up. Launch rails console and create a bunch of Parties, Festivals, and MultiEventFestival and say one of the MultiEventFestivals you created got an id of 52 assigned to it.
Next time you fire up your console(or when the code below is touched somewhere in your Rails app) chances are you'll get ActiveRecord::RecordNotFound: in response to Festival.find 52 call(remember Festival number 52 is a MultiEventFestival which is a subclass of Festival and Festival in turn is a subclass of Party and they all are STI models that live in one shared table parties)

Festival.find 52
Festival Load (0.3ms)  SELECT `parties`.* FROM `parties` WHERE `parties`.`type` IN ('Festival') AND `parties`.`id` = 52 LIMIT 1 ActiveRecord::RecordNotFound: Couldn't find Festival with id=52 [WHERE `parties`.`type` IN ('Festival')]

ActiveRecord query generated doesn't search for the model in the whole scope of Party subclasses, only in Festival since it was lazy loaded by calling Festival.find 52 unlike MultiEventFestival that wasn't called at all yet.

This happens only in development mode due to how Rails lazy loads classes(you won't have this problem in production mode because in production all the classes get loaded once and cached).
So to save you some google search time here is the solution.


Create an initializer file(say sti_class_initializer.rb) and put there

[Festival, MultiEventFestival] if Rails.env == 'development'

It will load Festival and MultiEventFestival classes on application's launch therefor forcing Rails to load STI subclasses in development mode.

Alex Bush @alex v bush