在 mongoid 中保存 embeds_many
Posted
技术标签:
【中文标题】在 mongoid 中保存 embeds_many【英文标题】:saving embeds_many in mongoid 【发布时间】:2012-10-02 19:20:58 【问题描述】:我有一个 embeds_many 关联,当我保存父文档时,没有保存子文档。
class User
include Mongoid::Document
embeds_many :user_missions
attr_accessible :user_missions_attributes
accepts_nested_attributes_for :user_missions, allow_destroy: true
end
class UserMission
include Mongoid::Document
embedded_in :user, :inverse_of => :user_missions
has_one :mission, autosave: true
validates_presence_of :mission
attr_accessible :mission_title
def mission_title
mission.try(:title)
end
def mission_title=(title)
self.mission = Mission.find_or_create_by(:title => title) if title.present?
end
end
这是我失败的规范:
it "should save mission to user_mission when created" do
user_mission = UserMission.new
user = create(:user)
user.user_missions << user_mission
user_mission.mission_title = "Created Title"
user.save!
#user_mission.save!
User.first.user_missions[0].mission.title.should == "Created Title"
end
我明白了:
undefined method `title' for nil:NilClass
当我在#user_mission.save!
行中发表评论时,它起作用了。问题是我需要它在表单中工作,我认为 Mongoid 会自动保存嵌入文档的字段。
如何获取父 User 文档来保存嵌入的 UserMission 的数据?
谢谢
更新
这是我忘记添加的任务模型(不确定是否重要):
class Mission
include Mongoid::Document
belongs_to :user_mission, :inverse_of => :mission
attr_accessible :title
field :title, type: String
validates_presence_of :title
field :lowercase_title
before_create :lower_title_case
field :description, type: String
private
def lower_title_case
self.lowercase_title = self.title.downcase
end
end
【问题讨论】:
【参考方案1】:AFAIK,嵌入式文档不能有引用关系。所以对embedded_in
和has_one
的调用是矛盾的。
除此之外,您是否尝试过重新排序测试中的行,以便首先创建用户,然后通过用户创建user_misison
?
user = create(:user)
user_mission = user.user_missions.new
user_mission.mission_title = "Created Title"
user.save!
看起来您正在尝试执行的操作类似于 SQL JOIN 表。如果这是您想要实现的目标,那么最好利用 Mongoid 令人敬畏的 N-N 引用映射(除非您需要在“加入”集合中存储额外的数据)。我会做类似的事情:
class User
include Mongoid::Document
has_and_belongs_to_many :missions
end
class Mission
include Mongoid::Document
has_and_belongs_to_many :users
end
如果您想通过用户创建任务,请在关系的任务端打开自动保存。
编辑:看到您的任务模型后,我意识到您正试图直接从您的任务模型中直接引用嵌入文档 UserMission (belongs_to :user_mission
)。就像我之前说的,不可行。您需要***文档、用户和任务之间的某种关系。您可以通过将该行更改为:
has_many :users
然后将 has_one :mission
从 User 模型更改为:
belongs_to :mission
但您将无法从用户端使用自动保存。
编辑:更正了正确的方式来展示从用户到任务的 1-n 关系的正确方式。
【讨论】:
我确实创建了“join”表来存储我稍后将添加的额外信息(例如创建时间)。此外,用户 embeds_many UserMissions 和 UserMissions 是在用户中嵌入的。还有一个我忘记包含的模型,称为 Mission,UserMission 与之有 has_one 关系(我现在将在更新中添加它。)我刚刚尝试重新排序,但没有成功。 在看到任务课程后编辑。 另外,请确保您在测试中创建了一个 Mission 实例。最后一行需要更改为User.first.mission.title.should == "Created Title"
,而不是通过user_mission。我建议编写一个单独的测试以确保正确设置 user_mission 的标题。
删除任务中的belongs_to
并将user_mission 中的has_one :mission, autosave: true
更改为belongs_to :mission, :inverse_of => nil
有效。谢谢。如果我想查找具有特定任务的所有 UserMissions,您是否建议我使用参考文档而不是嵌入文档?
是的,您需要为此使用参考文档。或者,如果您设置了用户和任务之间的关系,您可以简单地查询与特定任务相关的用户,然后枚举他们以提取嵌入的 user_mission。以上是关于在 mongoid 中保存 embeds_many的主要内容,如果未能解决你的问题,请参考以下文章
使用 mongoid 在 rails 中保存带有嵌入对象/文档的对象