Embes_many and embeds_one from the same model with Mongoid

I have two models: a blog and a theme. Embeds_many blog: topics and embedded_in: blog theme. I also have an embeds_one: theme blog (for an activated theme). This does not work. When you create a topic from blog.themes.create it is not saved. If I change the collections so that they are not implemented, everything works.

 # This does NOT work! class Blog embeds_many :themes embeds_one :theme end class Theme embedded_in :blog end 

BUT

 # This DOES work! class Blog has_many :themes has_one :theme end class Theme belongs_to :blog end 

Does anyone know why this is?

UPDATE

There is also a problem with assigning one of the topics to the (selected) topic.

 blog.themes = [theme_1, theme_2] blog.save! blog.theme = blog.themes.first blog.save! blog.reload blog.theme # returns nil 
+6
source share
3 answers

With this approach, you insert the same document twice: once into a collection of topics, and then into a highlighted topic.

I would recommend removing the second relationship and using a string attribute to store the current topic name. You can do something like:

 class Blog include Mongoid::Document field :current_theme_name, type: String embeds_many :themes def current_theme themes.find_by(name: current_theme_name) end end class Theme include Mongoid::Document field :name, type: String embedded_in :blog end 

Please note that nested documents of mongoids are initialized simultaneously with the main document and do not require additional queries.

+2
source

OK, so I had the same problem, and I thought I just came across a solution (I checked the code for the metadata for the relationships ).

Try the following:

 class Blog embeds_many :themes, :as => :themes_collection, :class_name => "Theme" embeds_one :theme, :as => :theme_item, :class_name => "Theme" end class Theme embedded_in :themes_collection, :polymorphic => true embedded_in :theme_item, :polymorphic => true end 

I have discerned , which suggested that:

  • the first parameter (for example :themes ) actually becomes the name of the method.
  • :as fakes the actual relationship, so it is imperative that they match in both classes.
  • :class_name seems pretty obvious, the class used to serialize data.

Hope this helps - I'm obviously not an expert on internal work on a mangoid, but that should be enough for you to work. My tests are now green and the data is being serialized as expected.

+1
source

Remove embeds_one :theme and instead put its getter and setter methods in the Blog class:

 def theme themes.where(active: true).first end def theme=(thm) theme.set(active: false) thm.set(active: true) end 

No need to call blog.save! after blog.theme = blog.themes.first , because set performs an atomic operation.

Also, be sure to add field :active, type: Boolean, default: false to your Theme model.

Hope this works for you.

+1
source

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


All Articles