在Mongoid中,将文档推送到embeds_many
关系会自动将文档保存到数据库中。通常,这很好,但是当我需要跟踪嵌入文档的更改时,我遇到了问题。
假设您有两种型号:
class List
include Mongoid::Document
embeds_many :items
field :title
end
class Item
include Mongoid::Document
embedded_in :list
field :name
end
这发生在.changes属性:
list = List.new(title: 'List title')
list.save #list is now persisted
item = Item.new(name: 'Item name')
item.changes #returns Hash with {'name' => [nil, 'Item name']}
list.items << item #saves item to database under the hood
item.changes #returns empty Hash, because item was autosaved with list
我可以使用item.previous_changes
来检查在将项目推入列表之前所做的更改,但在我的具体情况下,这会给我带来各种麻烦以保持可管理性。
我希望实现的目标是能够初始化Item
文档,然后将其添加到list
(通过<<
或push
),而不必将其保留立即
我知道Mongoid确实提供了一个选项来设置embeds_many
关系而不会持久化(参见http://mongoid.org/en/mongoid/docs/relations.html#embeds_many):
list.items.build(name: 'Another item')
问题在于Mongoid为您创建了Item实例。就我而言,embeds_many
关系中的文档可能是Item的子类(例如SpecialItem < Item
),这对build
不起作用。但如果有人知道如何解决这个限制,我也很乐意接受它作为答案。
答案 0 :(得分:4)
回答我自己的问题:通过将父文档分配给子项来解决问题,而不是将子项添加到列表或子项中。
继续上面的例子,你应该做
item.list = list #no database query
而不是
list.items << item #automatic database insert
设置父子引用,而不对数据库进行任何自动保护。
答案 1 :(得分:2)
要使用您的示例跟进“构建子类”问题,您可以:
list.items.build({
name: "Another Item"
}, SpecialItem)
指定您希望Mongoid为您构建的(子)类。