【发布时间】:2013-11-27 17:15:47
【问题描述】:
使用 Mongoid3,我正在尝试将多态性添加到我的嵌入式关系中。
我有一个类Item,它必须embed_one 包含我的信息的对象。
交易是:
- 我的对象的类型可以是其中之一:Calendar、Sticker、Picture;
- 无论我的对象是什么类型,我都想通过一个唯一的“键”来访问它:detail
例如:
pry> my_item1.detail
=> `<Picture _id: 1234>`
pry> my_item2.detail
=> `<Sticker _id: 8964>`
pry>
首先,我尝试使用关键字 as 和 polymorphic,如下所述:https://github.com/mongoid/mongoid/issues/902
例如:
class Item
include Mongoid::Document
embeds_one :detail, as: :item_slot
end
class Picture
include Mongoid::Document
embedded_in :item_slot, polymorphic: true
end
class Calendar
include Mongoid::Document
embedded_in :item_slot, polymorphic: true
end
class Sticker
include Mongoid::Document
embedded_in :item_slot, polymorphic: true
end
然后我尝试访问我的详细信息,但不幸的是,我收到了此消息错误:
pry(main)> i = Item.new
pry(main)> i.detail
=> nil
pry(main)> i.detail = Picture.find('50b864').dup
pry(main)> i.save
=> true
pry(main)> i = Item.find i._id
pry(main)> i.detail
NameError: uninitialized constant Detail
from /home/jg/.rvm/gems/ruby-1.9.3-p448/gems/activesupport-3.2.14/lib/active_support/inflector/methods.rb:230:in `block in constantize'
它说 mongoid 在我的 item 中没有找到任何 .detail。为什么不。
然后,我发现这个话题mongoid polymorphic association error 告诉添加class_name。所以我像这样更新了我的代码:
class Item
include Mongoid::Document
embeds_one :detail, class_name: "Picture", class_name: "Calendar", class_name: "Sticker"
end
让我们试试吧:
pry(main)> i.detail = Picture.find('50b864').dup
pry(main)> i.save
=> true
pry(main)> i = Item.find i._id
pry(main)> i.detail
=> #<Sticker _id: 52961d>
这很尴尬,因为我希望得到Picture,而不是Sticker (里面有我图片的值)。 (如果我将每个不同的 class_name 值放在新行上,结果是相同的。)
对于我的第三次尝试,我像这样使用Custom Relation Names:
class Item
include Mongoid::Document
embeds_one :detail, class_name: "Picture", class_name: "Calendar", class_name: "Sticker", inverse_of: :item_slot
end
class Picture # for Calendar and Sticker too ofc
include Mongoid::Document
embedded_in :item_slot, polymorphic: true, inverse_of: :detail
end
但它也给了我一个贴纸。
我什至尝试过:
class Item
include Mongoid::Document
embeds_one :detail, inverse_of: :item_slot
end
但它再次向我发送之前看到的 NameError。
我最后一次尝试是使用继承:
class Item
include Mongoid::Document
embeds_one :detail
end
class Detail
include Mongoid::Document
embedded_in :item
end
# Same again for Calendar and Sticker
class Picture < Detail
... # regular other fields
end
但是在为sticker.rb 和calendar.rb 午餐pry 时它给了我可怕的信息
DEVEL - Failed to load .../models/sticker.rb; removing partially defined constants
DEVEL - Problem while loading .../models/sticker.rb: uninitialized constant Detail
我没有更多的想法..
==> 有人给点建议吗?
编辑:
有一个等价于Hash[e.attributes] 就像这里的Extract `Moped::BSON::Document` attributes in Ruby hash 然后这样做会很好:
class Item
include Mongoid::Document
field :detail
end
将我的Picture、Calendar 和Sticker 保留为类实例(因为我有不同的方法可以在保存后应用)。
JG
编辑:替代方式
编辑 08/08/2014,将该部分拆分为该主题的答案。
【问题讨论】:
-
这个问题真的很糟糕,我认为你应该对这篇文章有所了解。您应该添加您所做的“编辑”作为答案。
-
@JúlioTurollaRibeiro,完成。感谢您的建议!
标签: ruby mongoid polymorphic-associations