蒙古语嵌入关系中的实际多态性

jgb*_*ret 3 ruby polymorphic-associations mongoid

我正在尝试使用Mongoid3将多态添加到我的嵌入关系中。

我有一个Item必须包含我的信息的embed_one对象的类。该协议是:
-我对象的类型可以是其中之一:CalendarStickerPicture
-无论对象的类型如何,我都想通过唯一的“键”来访问它:详细信息,
例如:

pry> my_item1.detail  
=> `<Picture _id: 1234>`  
pry> my_item2.detail  
=> `<Sticker _id: 8964>`
pry>
Run Code Online (Sandbox Code Playgroud)

首先,我尝试使用关键字as和此处描述的多态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
Run Code Online (Sandbox Code Playgroud)

然后,我尝试访问我的详细信息,但不幸的是,我收到此消息错误:

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'
Run Code Online (Sandbox Code Playgroud)

它说蒙古人没有找到任何.detail东西item。为什么不。

然后,我发现该主题mongoid多态关联错误告诉添加class_name。所以我像这样更新了我的代码:

class Item  
    include Mongoid::Document
    embeds_one  :detail, class_name: "Picture", class_name: "Calendar", class_name: "Sticker"
end
Run Code Online (Sandbox Code Playgroud)

我们试试吧:

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>
Run Code Online (Sandbox Code Playgroud)

这很尴尬,因为我期望得到一个Picture,而不是Sticker (它包含我的照片的值)。(如果将每个不同的class_name值放在新行上,结果是相同的。)

第三次尝试,我使用“ 自定义关系名称”,如下所示:

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  
Run Code Online (Sandbox Code Playgroud)

但这也给了我一个贴纸。
我什至尝试过:

class Item  
    include Mongoid::Document
    embeds_one  :detail, inverse_of: :item_slot
end  
Run Code Online (Sandbox Code Playgroud)

但是它再次向我发送了先前看到的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  
Run Code Online (Sandbox Code Playgroud)

但这在午餐中 为sticker.rb和calendar.rb 撬动时给了我可怕的信息

 DEVEL -  Failed to load .../models/sticker.rb; removing partially defined constants
 DEVEL -  Problem while loading .../models/sticker.rb: uninitialized constant Detail  
Run Code Online (Sandbox Code Playgroud)

我没有更多的主意。
==>有人提示吗?

编辑
最好有一个Hash[e.attributes]类似这里的Ruby哈希中提取`Moped :: BSON :: Document`属性,然后像这样:

class Item
    include Mongoid::Document
    field :detail
end  
Run Code Online (Sandbox Code Playgroud)

保留我的PictureCalendarSticker作为类实例(因为保存后每种方法都有不同的方法)。

JG

编辑:另一种方式
编辑08/08/2014,拆分该部分作为该主题的答案。

com*_*tos 5

您应该同时使用具有多态关系的继承关系:

基类

class Resource
  include Mongoid::Document
  include Mongoid::Timestamps

  embedded_in :resoursable, polymorphic: true
end
Run Code Online (Sandbox Code Playgroud)

小孩

class Photo < Resource
  field :width,  type: Integer
  field :height,  type: Integer
end

class Video < Resource
  field :url,  type: String
end
Run Code Online (Sandbox Code Playgroud)

嵌入

class Post
  include Mongoid::Document
  include Mongoid::Timestamps

  embeds_one :media, as: :resoursable, class_name: 'Resource'
end
Run Code Online (Sandbox Code Playgroud)

p = Post.last
resource = Photo.new
p.media = resource
p.save!
Run Code Online (Sandbox Code Playgroud)