In Mongoid, pushing a document into an embeds_many
relation automatically persists the document to the database. Normally, this is fine, but I run into problems when I need to track changes to the embedded document.
Say you have two models:
class List
include Mongoid::Document
embeds_many :items
field :title
end
class Item
include Mongoid::Document
embedded_in :list
field :name
end
This happens to the .changes attribute:
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
I could use item.previous_changes
to inspect the changes that were made before pushing the item into the list, but in my specific case, this would give me all kinds of troubles to keep things manageable.
What I would like to achieve, is to be able to initialize an Item
document and then add it to list
(via <<
or push
) without persisting it immediately.
I'm aware that Mongoid does provide an option to set up embeds_many
relations without persisting (see http://mongoid.org/en/mongoid/docs/relations.html#embeds_many):
list.items.build(name: 'Another item')
The problem there is that Mongoid creates the Item instance for you. In my case, the documents in the embeds_many
relation may be subclasses of Item (e.g. SpecialItem < Item
), which wouldn't work well with build
. But if anyone knows of a way to get around this limitation, I'd also be happy to accept it as an answer.
- GeeksforGeeks How to push data in a MongoDB document ? The insertOne () and insertMany () are the two methods of the MongoDB module in node.js that are used to push the documents in the collections of the MongoDB database.
Documents that are embedded using the embeds_one macro are stored as a hash inside the parent in the parent's database collection. You can optionally tell Mongoid to store the embedded document in a different attribute other than the name, by providing a :store_as option.
All relation objects in Mongoid are proxies to the actual document or documents themselves, which provide extra functionality for accessing, replacing, appending and persisting.
In MongoDB, you can only nest document up to 100 levels. The overall document size must not exceed 16 MB. Creating Embedded Documents – In MongoDB, you can easily embed a document inside another document.
To answer my own question: the problem is solved by assigning the parent document to the child, instead of adding the child to the list of children.
Continuing on the example above, you should do
item.list = list #no database query
instead of
list.items << item #automatic database insert
to set the parent - child reference without autosaving anything to the database.
To follow up on the "building a subclass" issue using your example, you can:
list.items.build({
name: "Another Item"
}, SpecialItem)
To specify the (sub)class that you want Mongoid to build for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With