埋め込みとmongoid 8.xでポリモーフィズムを機能させる方法について混乱しています。
class Entity
include Mongoid::Document
embeds_many :custom_fields, as: :item
end
class EmailField
include Mongoid::Document
field :name, type: String
field :value, type: String
embedded_in :item, polymorphic: true
end
class MultivalueField
include Mongoid::Document
field :name
field :value, type: Array
embedded_in :item, polymorphic: true
end
なぜこれが機能しないのかわかりません。私が期待しているのは、モデル エンティティにさまざまなタイプの多くのフィールドが埋め込まれていることですが、それは次のように爆発します。
NameError:
uninitialized constant MetadataService::Models::Entity::CustomField
私の何が間違っているのでしょうか?
Mongoid は embeds_many によるポリモーフィズムをサポートしていません。代わりに、継承を使用して、共通の祖先を参照することで、異なるクラスのドキュメントを埋め込むことができます。
class Entity
include Mongoid::Document
embeds_many :items
end
class Item
include Mongoid::Document
embedded_in :entity
field :name, type: String
end
class EmailItem < Item
field :value, type: String
end
class MultivalueItem < Item
field :value, type: Array
end
「フィールド」の代わりに「アイテム」を使用しているのは、後者が Mongoid では特別な意味を持ち、予約語とみなされているためです。この制限を回避するには、おそらく embeds_many :items, class_name: ‘Field’ を使用できますが、私は例をできるだけ単純にしておきたいと思いました。
使用法:
e = Entity.new
e.items << EmailItem.new(name: 'email', value: '[email protected]')
e.items << MultivalueItem.new(name: 'email', value: [1, 2, 3])
e.as_document
#=> {
# "_id"=>BSON::ObjectId('660e7a7e571de609e1c84723'),
# "items"=>[
# {
# "_id"=>BSON::ObjectId('660e7a7e571de609e1c84724'),
# "name"=>"email",
# "value"=>"[email protected]",
# "_type"=>"EmailItem"
# },
# {
# "_id"=>BSON::ObjectId('660e7a7e571de609e1c84725'),
# "name"=>"email",
# "value"=>[1, 2, 3],
# "_type"=>"MultivalueItem"
# }
# ]
# }
ビルド経由で項目のクラスを渡し、別の引数としてヘルパーを作成することもできます。
e.items.build({ name: 'email', value: '[email protected]' }, EmailItem)
e.items.build({ name: 'email', value: [1, 2, 3] }, MultivalueItem)