Lazy recognition of inheritance hierarchy in STI

Hi --

Given an STI setup like this:

    Substitute < Teacher < Person

I get the following, when there's one Substitute in the database:

Teacher.find(:first)

=> nil

Substitute.find(:first)

=> #<Substitute:0xb7579fec @attributes={"name"=>"David Black", "type"=>"Substitute", "id"=>"1"}>

Teacher.find(:first)

=> #<Substitute:0xb7576be4 @attributes={"name"=>"David Black", "type"=>"Substitute", "id"=>"1"}>

In other words, Teacher is not recognized as a superset of Substitute at first -- but is, after I've searched for a Substitute. The difference, in SQL terms, is:

   (people.`type` = 'Substitute' )

vs.

   (people.`type` = 'Teacher' OR people.`type` = 'Substitute' )

It seems to me that the inheritance behavior should be one way or the other, and not change dynamically. Or is there a reason for the change?

David

This happens because the Substitute model had not been loaded at the time of the Teacher.find(:first) call. By the time the second call was made, the Substitute model had been referenced and, therefore, substitute.rb had been loaded.

One option would be to explicitly load the substitute model in teacher.rb:

require_dependency ‘substitute’

-Jonathan.

Hi --

Hi --

Given an STI setup like this:

    Substitute < Teacher < Person

I get the following, when there's one Substitute in the database:

Teacher.find(:first)

=> nil

Substitute.find(:first)

=> #<Substitute:0xb7579fec @attributes={"name"=>"David Black", "type"=>"Substitute", "id"=>"1"}>

Teacher.find(:first)

=> #<Substitute:0xb7576be4 @attributes={"name"=>"David Black", "type"=>"Substitute", "id"=>"1"}>

In other words, Teacher is not recognized as a superset of Substitute at first -- but is, after I've searched for a Substitute. The difference, in SQL terms, is:

   (people.`type` = 'Substitute' )

vs.

   (people.`type` = 'Teacher' OR people.`type` = 'Substitute' )

It seems to me that the inheritance behavior should be one way or the other, and not change dynamically. Or is there a reason for the change?

This happens because the Substitute model had not been loaded at the time of the Teacher.find(:first) call. By the time the second call was made, the Substitute model had been referenced and, therefore, substitute.rb had been loaded.

One option would be to explicitly load the substitute model in teacher.rb:

require_dependency 'substitute'

Thanks -- that does indeed work. I'm just surprised (I guess I never ran into it before) that there isn't more eager loading/checking for subclasses, since the possibility exists that they will be there, and since it's acknowledged that Teacher.find(n) can be a Substitute. I could understand if a decision had been made that Superclass.find(n) would *never* include subclasses... but since that's not the case, it's odd to me that it flips from one behavior to the other.

Perhaps I shall write an eager_sti plugin.... :slight_smile:

David