Rails: Подкаталоги Single Table Inheritance и models - PullRequest
3 голосов
/ 26 мая 2010

У меня есть приложение для карточных игр, в котором используется наследование одного стола. У меня есть class Card и таблица базы данных cards со столбцом type, а также ряд подклассов Card (включая class Foo < Card и class Bar < Card, для аргумента).

Как оказалось, Foo - карта из оригинального издания игры, а Bar - карта из расширения. В попытке рационализировать мои модели, я создал структуру каталогов следующим образом:

app/
+ models/
  + card.rb
  + base_game/
    + foo.rb
  + expansion/
    + bar.rb

И модифицированный файл environment.rb, содержащий:

Rails::Initializer.run do |config|
  config.load_paths += Dir["#{RAILS_ROOT}/app/models/**"]
end

Однако, когда мое приложение считывает карту из базы данных, Rails выдает следующее исключение:

ActiveRecord::SubclassNotFound (The single-table inheritance mechanism failed to locate the subclass: 'Foo'. 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 Card.inheritance_column to use another column for that information.)

Возможно ли заставить это работать, или я обречен на плоскую структуру каталогов?

1 Ответ

2 голосов
/ 26 мая 2010

Вероятно, лучший способ сделать это - поместить класс Foo в модуль BaseGame.

Модуль ruby ​​примерно похож на структуру пакета в других языках, это механизм для разделения связанных битов кода на логические группы. У него есть другие функции, такие как миксины (которые вы можете найти объяснено здесь: http://www.rubyfleebie.com/an-introduction-to-modules-part-1/), но в данном случае они не актуальны.

Вам нужно будет ссылаться и создавать экземпляр класса немного по-другому. Например, вы бы запросили это так:

BaseGame::Foo.find(:all,:conditons => :here)

Или создайте его экземпляр так:

BaseGame::Foo.new(:height => 1)

Rails поддерживает модульный код для моделей Active Record. Вам просто нужно внести несколько изменений в место хранения класса. скажем, например, вы перемещаете класс Foo в модуль BaseGame (как в вашем примере), вам нужно переместить apps/models/foo.rb в apps/models/base_game/foo.rb. Так что дерево файлов будет выглядеть так:

app/
 + models/
  + card.rb #The superclass
   + base_game/
      + foo.rb

Чтобы объявить это в классе, определите так:

module BaseGame
  class Foo < Card
  end
end
...