Rails:单表继承和模型子目录

时间:2010-05-26 12:49:59

标签: ruby-on-rails directory-structure single-table-inheritance

我有一个使用单表继承的纸牌游戏应用程序。我有一个class Card,一个数据库表cards,列type,以及一些Card的子类(包括class Foo < Cardclass 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 个答案:

答案 0 :(得分:2)

执行此操作的最佳方法可能是将Foo类嵌套在BaseGame模块中。

ruby​​模块大致类似于其他语言的包结构,它是一种将相关代码位划分为逻辑组的机制。它还有其他功能,例如mixins(你可以在这里解释: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