我有一个使用单表继承的纸牌游戏应用程序。我有一个 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?
发布评论
评论(1)
也许最好的方法是将
Foo
类嵌套在BaseGame
模块中。ruby 模块与其他语言中的包结构大致相似,它是一种将相关代码位划分为逻辑组的机制。它还有其他功能,例如 mixins(您可以在这里找到解释: http://www.rubyfleebie.com/an-introduction-to-modules-part-1/),但在这种情况下它们不相关。
您需要以稍微不同的方式引用和实例化该类。例如,您可以像这样查询它:
或者像这样创建它的实例:
Rails 支持 Active Record 模型的模块化代码。您只需对类的存储位置进行一些更改即可。举例来说,您将类 Foo 移动到模块 BaseGame 中(如您的示例所示),您需要将
apps/models/foo.rb
移动到apps/models/base_game/foo.rb
。所以你的文件树将如下所示:要在类定义上声明它,如下所示:
Probably the best way to do this would be to nest the
Foo
class inside aBaseGame
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:
Or create an instance of it like this:
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
toapps/models/base_game/foo.rb
.So you're file tree will look like:To declare this on the class define like so: