从Mongoid文档中我看到如果我有以下内容:
class Base
include Mongoid::Document
end
class InheritedA < Base
end
class InheritedB < Base
end
我可以执行以下操作,它将与“_type”属性一起存储。
a = InheritedA.new
a.save
Mongoid将创建以下文档。
{ _type: "InheritedA" }
我的问题是,稍后我有一个只有String _type值的函数,我希望实例化正确的类型。我试过这个:
Base.new({ _type: mytype });
然而,Mongoid认为这是一个动态属性并拒绝它。我知道打开动态属性不是正确的过程,因为我不想在一般情况下允许这种行为。
我想避免做这样的事情:
ob = nil
if mytype == "InheritedA"
ob = InheritedA.new
elsif
...
有谁知道实现这个目标的正确方法?
答案 0 :(得分:3)
有两种方法可以解决这个问题。第一个创建基类文档,然后将其转换为子类文档。使用此方法,您只能基于基类中定义的字段进行初始化:
# attributes = {base_key1: value1, base_key2: value2}
Base.new(attributes).becomes(mytype.constantize)
第二个直接创建子类的文档,您可以初始化子类的任何字段:
# attributes = {base_key1: value1, base_key2: value2, sub_key3: value3}
Mongoid::Factory.build(mytype.constantize, attributes)
答案 1 :(得分:1)
在查看Mongoid源代码后,我意识到Mongoid确实尝试在查看_type字段时实例化正确的类型,当有人做这样的事情时:
Base.new({ _type: "InheritedA" })
通过查看基类的后代来实现。显然我的ruby类是延迟加载的,默认情况下Base.descendants调用返回一个空列表!我不确定这是由于使用JRuby,还是关于Rails开发模式的怪癖,或者是config.cache_classes值,还是别的,但我能够通过这样做来解决它:
class Base
Descendant1.inspect
Descendant2.inspect
...
是的,这真的很痛苦,但它允许你使用Rails重新加载你的课程。