Mongoid confused with embedded document with timestamps and version?

I've been using Mongoid for about 3 months now, and I managed to do everything I need thanks to an excellent document and resources.

But, returning to improve some of the things that I did a few spin, I definitely struggle a lot with embedded documents.

In short, what I'm trying to do is maintain versions and timestamps in embedded documents, but I cannot do this.

Here is the relevant part of my model:

class Content include Mongoid::Document include Mongoid::Timestamps include Mongoid::Paranoia embeds_many :localized_contents accepts_nested_attributes_for :localized_contents end class LocalizedContent include Mongoid::Document include Mongoid::Timestamps include Mongoid::Paranoia include Mongoid::Versioning embedded_in :content, :inverse_of => :localized_contents end 

There is nothing complicated here, everything works fine with the behavior of the Content model, however, the LocalizedContent model does not behave as I expect, so my expectations either need to be fixed, or I need help in fixing what I'm doing wrong.

To create a new inline document, I do the following:

 my_content = Content.find(params[:id]) my_content.localized_contents.build(params[:localized_content]) if parent.save #redirect, etc. end 

This works in the sense that it successfully creates a new embedded document in the correct Content, however in the timestamps fields I left nil

Now, if I try to update this localized_content:

 my_content = Content.find(params[:content_id]) localized_content = my_content.localized_contents.find(params[:id]) 

Now, if I do this: localized_content.update_attributes(params[:localized_content]) I get the following error:

 => Mongoid::Errors::InvalidCollection: Access to the collection for LocalizedContent is not allowed since it is an embedded document, please access a collection from the root document. 

Fair enough, then I automatically update the localized content fields and save the parent:

 localized_content.fieldA = "value" localized_content.fieldB = "value" localized_content.fieldC = "value" my_content.save 

This works if the localized content is updated correctly, but: - timesteamps (udpated_at and created_at) are still zero - versions do not receive a copy of the current localized content, and the version does not increase.

Thus, when I read many times in these groups and on some forums on the Internet, callbacks do not start in the embedded document due to performance reasons, since I call save on the parent. Again, enough, but as suggested in these places, I have to call save on embedded documents ... but how!?!?! because every time I get fear:

 => Mongoid::Errors::InvalidCollection: Access to the collection for LocalizedContent is not allowed since it is an embedded document, please access a collection from the root document. 

Moreover, I tried to manually call the version control call on my built-in: localized_content.revise and again the same error:

 => Mongoid::Errors::InvalidCollection: Access to the collection for LocalizedContent is not allowed since it is an embedded document, please access a collection from the root document. 

I'm going down here! Please help. What am I doing wrong? How do I create and update an embedded document so that I can (even not manually bother me) the proper callbacks to update timestamps and versions?

Thanks,

Alex

ps: I am using rails 3.0.3 and mongoid 2.0.1

+4
source share
2 answers

Just in case, this answer is still useful for everyone, Mongoid added a tag that calls callbacks in the built-in child objects while saving the parent object.

Your parent should now look like this:

 class Content include Mongoid::Document include Mongoid::Timestamps include Mongoid::Paranoia embeds_many :localized_contents, cascade_callbacks: true accepts_nested_attributes_for :localized_contents end 

What is it! Saving the parent object will now result in callbacks to the child objects (and Mongoid::Timestamps is smart enough to only work on objects that have actually been changed). This information is contained in the mongoid documentation at the very bottom of the embedded documents page.

+13
source

Try using create instead of build. EmbeddedDoc.build and EmbeddedDoc.new will not trigger any callbacks (since nothing is saved), and saving the parent document will not call the callbacks of the built-in children (performance decision). However, EmbeddedDoc.create must trigger embedded document callbacks.

 my_content = Content.find(params[:id]) puts my_content.localized_contents.create(params[:localized_content]) 
+4
source

Source: https://habr.com/ru/post/1347487/


All Articles