views:

40

answers:

1

app/models

class Amodel < ActiveRecord::Base
end

class Bmodel < Amodel
end

class Cmodel < Bmodel  
end

db/migrate

create_table :amodels do |t|
  t.string :type
end

on script/console...

$ script/console
Loading development environment (Rails 2.3.4)
>> Cmodel.create
=> #<Cmodel id: 1, type: "Cmodel">
>> Bmodel.find(:all)
=> [#<Cmodel id: 1, type: "Cmodel">]

ok, but Bmodel returns no records after rebooting console like:

>> exit
$ script/console
Loading development environment (Rails 2.3.4)
>> Bmodel.find(:all)
=> []

however, it works after accessing Cmodel:

>> Cmodel
=> Cmodel(id: integer, type: string)
>> Bmodel.find(:all)
=> [#<Cmodel id: 1, type: "Cmodel">]

Amodel works like:

>> exit
$ script/console
Loading development environment (Rails 2.3.4)
>> Amodel.find(:all)
=> [#<Cmodel id: 1, type: "Cmodel">]

Does anyone know why it works like this?

Rails: 2.3.4
Ruby: 1.8.7
OS: Ubuntu 9.0.4

A: 

Because of the way ActiveRecord STI is built. When a class is loaded, it registers with it's parent (see the #inherited hook). Thus, when you call Amodel#find or Bmodel#find, if the subclass isn't known, it can't be found yet.

In production, this problem wouldn't be apparent, because Rails will load all models when it starts, preventing this kind of problem.

François Beausoleil
Thank you for the simple answer! Afterwards, forcing Cmodel to be loaded in initializer, Bmodel#find has been able to return Cmodel objects without any other tricks.
sho1
Because Cmodel references Bmodel, loading Cmodel forces Bmodel to load, which is why you don't need any other references.
François Beausoleil