在Rails中使用STI时出现ActiveRecord :: SubclassNotFound错误

时间:2010-11-09 21:42:48

标签: ruby-on-rails activerecord single-table-inheritance

我正在使用Ruby on Rails 2.3.10。我有一个班级,School。我使用STI为我提供了几个子类:PrimarySchoolSecondarySchoolUniversity

app/models/primary_school.rb:
  class PrimarySchool < School
     has_many :education_records, :foreign_key => "school_id"
  end

app/models/secondary_school.rb:
  class SecondarySchool < School
     has_many :education_records, :foreign_key => "school_id"
  end

app/models/university.rb
  class University < School
     has_and_belongs_to_many :applicants, :join_table => :applicants_schools, :foreign_key => "school_id"
  end

db/migrate/20100824170203_create_schools.rb:
class CreateSchools < ActiveRecord::Migration
  def self.up
    create_table :schools do |t|
      t.string :name
      t.string :type     # secondary, cegep, college, university
      t.string :street
      ...
      t.timestamps
    end
  end

  def self.down
    drop_table :schools
  end
end

PrimarySchool.firstPrimarySchool.last按预期工作。 SecondarySchool.firstSecondarySchool.last按预期工作。 University.last有效。

但是,University.firstUniversity.all会引发ActiveRecord::SubclassNotFound例外:

ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass: 'University'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this column if you didn't intend it to be used for storing the inheritance class or overwrite University.inheritance_column to use another column for that information.
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:1671:in `instantiate'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:665:in `find_by_sql'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:665:in `collect!'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:665:in `find_by_sql'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:1582:in `find_every'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:619:in `find'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.10/lib/active_record/base.rb:639:in `all'
    from (irb):6
    from :0

生成的SQL是正确的:

  SecondarySchool Load (0.3ms)   SELECT * FROM `schools` WHERE ( (`schools`.`type` = 'University' ) ) LIMIT 1
  SecondarySchool Load (1.7ms)   SELECT * FROM `schools` WHERE ( (`schools`.`type` = 'University' ) ) ORDER BY schools.id DESC LIMIT 1

我错过了什么/做错了什么?

2 个答案:

答案 0 :(得分:3)

这是开发模式中的known issue

一种解决方法是在基类文件的底部注册子类。

%w(secondary_school university).each do |r| 
  require_dependency r
end if Rails.env.development?

答案 1 :(得分:2)

KandadaBoggu让我走上正轨。 Pete P.的解决方法对我有用:

class School < ActiveRecord::Base
  def self.subclasses
    [PrimarySchool, SecondarySchool, OtherSchool, University]
  end
end

因为它摆脱了异常......但它生成了错误的SQL:

SELECT * FROM `schools` WHERE ( (`schools`.`type` = 'University' OR
`schools`.`type` = 'PrimarySchool' OR `schools`.`type` = 'SecondarySchool' OR 
`schools`.`type` = 'OtherSchool' OR `schools`.`type` = 'PostSecondaryInstitution' OR 
`schools`.`type` = 'Cegep' OR `schools`.`type` = 'College' OR `schools`.`type` = 
'University' ) ) LIMIT 1

将university.rb重命名为uni.rb,更改类名和UPDATEing类型列使这项工作成功。我真的很困惑。