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