ActiveRecord :: SubclassNotFound ошибка при использовании STI в Rails - PullRequest
2 голосов
/ 10 ноября 2010

Я использую Ruby on Rails 2.3.10.У меня есть класс, School.Я использую STI, чтобы дать мне несколько подклассов: PrimarySchool, SecondarySchool и University.

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.first и PrimarySchool.last работают должным образом.SecondarySchool.first и SecondarySchool.last работают как положено.University.last работает.

Однако University.first и University.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 ]

3 голосов
/ 10 ноября 2010

Это известная проблема в режиме разработки.

Один из способов - зарегистрировать подклассы в нижней части файла базового класса.

%w(secondary_school university).each do |r| 
  require_dependency r
end if Rails.env.development?
2 голосов
/ 10 ноября 2010

KandadaBoggu поставил меня на правильный путь.Обходной путь Пита П. работает для меня:

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

Переименование университета.rbuni.rb, изменение имени класса и ОБНОВЛЕНИЕ столбца типа сделали эту работу.Я действительно запутался.

...