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

发布于 2024-09-03 09:00:20 字数 841 浏览 1 评论 0 原文

我有一个使用单表继承的纸牌游戏应用程序。我有一个 Card 类、一个带有 type 列的数据库表 cards 以及许多 Card 的子类(为了便于论证,包括 class Foo class Bar )。

碰巧,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 (单表继承机制无法定位子类:'Foo'。出现此错误是因为保留'type'列用于在继承时存储类。如果您不希望此列重命名,请重命名用于存储继承类或覆盖 Card.inheritance_column 以使用另一列来存储该信息。)

是否可以完成这项工作,或者我注定要采用平面目录结构?

I have a card-game application which makes use of Single Table Inheritance. I have a class Card, and a database table cards with column type, and a number of subclasses of Card (including class Foo < Card and class Bar < Card, for the sake of argument).

As it happens, Foo is a card from the original printing of the game, while Bar is a card from an expansion. In an attempt to rationalise my models, I have created a directory structure like so:

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

And modified environment.rb to contain:

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

However, when my app reads a card from the database, Rails throws the following exception:

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.)

Is it possible to make this work, or am I doomed to a flat directory structure?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦屿孤独相伴 2024-09-10 09:00:20

也许最好的方法是将 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

Probably the best way to do this would be to nest the Foo class inside a BaseGame module.

A ruby module is roughly similar to a package structure in other languages, it's a mechanism for partitioning related bits of code into logical groups. It has other functions such as mixins (which you can find explained here: http://www.rubyfleebie.com/an-introduction-to-modules-part-1/) but in this instance they're not relevant.

You'll need to reference and instantiate the class slightly differently. For example you'd query it like this:

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

Or create an instance of it like this:

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

Rails supports modularized code for Active Record models. You just need to make a few changes to where the class is stored. say for example you move the class Foo into a module BaseGame (as in your example), you need to move apps/models/foo.rb to apps/models/base_game/foo.rb.So you're file tree will look like:

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

To declare this on the class define like so:

module BaseGame
  class Foo < Card
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文