【问题标题】:embeds_many and embeds_one from same model with Mongoidembeds_many 和 embeds_one 来自与 Mongoid 相同的模型
【发布时间】:2011-10-16 09:35:30
【问题描述】:

我有两个模型,博客和主题。博客 embeds_many :themes 和 Theme embedded_in :blog。我也有 Blog embeds_one :theme (用于激活的主题)。这不起作用。当使用blog.themes.create 创建主题时,它不会被存储。如果我更改集合以使其不被嵌入,那么一切正常。

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

class Theme
  embedded_in :blog
end

但是

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

class Theme
  belongs_to :blog
end

有人知道这是为什么吗?

更新

将主题之一分配给(选定的)主题也存在问题。

blog.themes = [theme_1, theme_2]
blog.save!

blog.theme = blog.themes.first
blog.save!

blog.reload
blog.theme # returns nil

【问题讨论】:

    标签: ruby-on-rails ruby mongodb mongoid


    【解决方案1】:

    使用这种方法,您将两次嵌入同一个文档:一次在主题集合中,然后在选定的主题中。

    我建议删除第二个关系并使用字符串属性来存储当前主题名称。您可以执行以下操作:

    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
    

    请注意,mongoid 嵌入文档与主文档同时初始化,不需要额外的查询。

    【讨论】:

      【解决方案2】:

      好的,所以我遇到了同样的问题,我想我只是偶然发现了解决方案(我正在查看code for the Metadata on relations)。

      试试这个:

      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
      

      辨别的猜测是:

      • 第一个参数(例如:themes)实际上成为方法名称。
      • :as 伪造实际关系,因此需要它们在两个类中匹配。
      • :class_name 看起来很明显,用于实际序列化数据的类。

      希望这会有所帮助 - 我显然不是 mongoid 内部工作的专家,但这应该足以让您运行。我的测试现在是绿色的,并且数据正在按预期进行序列化。

      【讨论】:

      • 嗯,那样对我不起作用。它仍然对您有用吗?
      • 是的,在我需要这个的有限情况下,它已经奏效了。
      【解决方案3】:

      删除 embeds_one :theme 并将其 getter 和 setter 方法放在 Blog 类中:

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

      没有必要在blog.theme = blog.themes.first 之后调用blog.save!,因为set 执行原子操作。

      另外,不要忘记在您的 Theme 模型中添加 field :active, type: Boolean, default: false

      希望这对你有用。

      【讨论】:

        猜你喜欢
        • 2013-02-09
        • 1970-01-01
        • 1970-01-01
        • 2014-05-19
        • 2012-01-16
        • 2012-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多