Problem:
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
end
class Festival < Party
end
class MultiEventFestival < Festival
end
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.
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