如何使用Mongoid更新Rails中的嵌套Mongo文档属性?

(如果这个问题的细节很短,请提前道歉,我会看评论并添加我能做的)

我有一个带有以下内容的模型:

class Product include Mongoid::Document include Mongoid::Timestamps #... field :document_template, :type => Document accepts_nested_attributes_for :document_template 

在document document_template中,是以下references_many,我想修改它。 具体来说,我想更改引用的字体:

 class Document include Mongoid::Document include Mongoid::Timestamps #... references_many :fonts, :stored_as => :array, :inverse_of => :documents 

我应该在控制器和表单中使用什么样的逻辑和细节来完成这项工作? 如果您希望我添加一些我尝试过的东西,请发表评论; 但是,我没有任何运气。

以下是使用rails console快速显示的问题:

 # Grab a Product and check how many fonts are in it's document_template ruby-1.8.7-p302 > prod = Product.find(:first) => ... ruby-1.8.7-p302 > prod._id => BSON::ObjectId('4d06af15afb3182bf5000111') ruby-1.8.7-p302 > prod.document_template.font_ids.count => 9 # Remove a font from the font_ids array ruby-1.8.7-p302 > prod.document_template.font_ids.pop => BSON::ObjectId('...') # This font id was removed from font_ids ruby-1.8.7-p302 > prod.document_template.font_ids.count => 8 # Save the changes ruby-1.8.7-p302 > prod.document_template.save! => true ruby-1.8.7-p302 > prod.save! => true # Instantiate a new product object of that same product ruby-1.8.7-p302 > prod_new = Product.find(:first) => ... # Confirm the _ids are the same ruby-1.8.7-p302 > prod._id == prod_new._id => true # Check to see if the changes were persisted ruby-1.8.7-p302 > prod_new.document_template.font_ids.count => 9 # If the changes persisted, this should be 8. # Grrrrr... doesn't look like it. Will the change disappear after a reload too? ruby-1.8.7-p302 > prod.reload => ... ruby-1.8.7-p302 > prod.document_template.font_ids.count => 9 # ಠ_ಠ ... no dice. 

使用mongo更新对象(而不是使用rails中的mongoid)按预期工作。

Kyle Banker已经要求提供一些日志信息,所以就在这里。 不幸的是,我找不到比rails服务器输出更好的日志记录来源,这似乎表明永远不会进行更新调用。 对于某些上下文,这里是控制器的一些信息:

 def update_resource(object, attributes) update_pricing_scheme(object, attributes) update_document_template_fonts(object, attributes) end def update_document_template_fonts(object, attributes) document_template = object.document_template document_template_attributes = attributes[:document_template_attributes] font_ids = document_template_attributes[:font_ids] font_ids.delete("") # Removing an empty string that tags along with the font_ids. font_ids.collect! { |f| BSON::ObjectId(f) } # Mongo want BSON::ObjectId object.document_template.font_ids.replace font_ids object.document_template.save!(:validate => false) object.save!(:validate => false) end 

以下是处理POST时rails服务器的输出:

 Started GET "/admin/products/4d091b18afb3180f3d000111" for 127.0.0.1 at Wed Dec 15 13:57:28 -0600 2010 Started POST "/admin/products/4d091b18afb3180f3d000111" for 127.0.0.1 at Wed Dec 15 13:57:49 -0600 2010 Processing by Admin::ProductsController#update as HTML Parameters: {"commit"=>"Update Product", "authenticity_token"=>"QUW0GZw7nz83joj8ncPTtcuqHpHRtp1liq8fB7/rB5s=", "utf8"=>"✓", "id"=>"4d091b18afb3180f3d000111", "product"=>{"name"=>"Ho Ho Ho Flat Multiple Photo Modern Holiday Card", "document_template_attributes"=>{"id"=>"4d091b18afb3180f3d000112", "font_ids"=>["", "4d091b17afb3180f3d000023"]}, "description"=>"", "pricing_scheme_id"=>"4d091b17afb3180f3d00003b"}} development['users'].find({:_id=>BSON::ObjectId('4d091b17afb3180f3d00009b')}, {}).limit(-1) development['products'].find({:_id=>BSON::ObjectId('4d091b18afb3180f3d000111')}, {}).limit(-1) development['pricing_schemes'].find({:_id=>BSON::ObjectId('4d091b17afb3180f3d00003b')}, {}).limit(-1) MONGODB development['products'].update({"_id"=>BSON::ObjectId('4d091b18afb3180f3d000111')}, {"$set"=>{"updated_at"=>Wed Dec 15 19:57:50 UTC 2010}}) in Document#set_default_color_scheme: self.color_scheme = # MONGODB development['documents'].update({"_id"=>BSON::ObjectId('4d091b18afb3180f3d000112')}, {"$set"=>{"color_scheme_name"=>"green_charcoal_black", "updated_at"=>Wed Dec 15 19:57:50 UTC 2010}}) Redirected to http://localhost:3000/admin/products/4d091b18afb3180f3d000111 Completed 302 Found in 49ms 

看起来更新font_ids的MONGODB命令完全不存在……

我偏爱相信Mongoid问题#357引起了这个问题。 上面的日志记录表明产品的document_template.fonts(或font_ids)的更新似乎与错误描述相匹配。

(旁注:我有点困惑,如果没有:stored_as =>:array,究竟font_ids数组来自哪里。我不是100%肯定我应该修改但是因为font_ids是一个数组而字体是一个Mongoid :: Criteria,阻力最小的路径是font_ids。)

从数据的角度来看,:field和:embeds_ *似乎相似,因为信息嵌入在父文档中。

Mongoid有一个复杂的后端。 因此,诊断此问题的最简单方法是启用驱动程序的日志记录。 然后我们可以看看在这两种情况下发送到数据库的确切消息,我们肯定会得到答案。

您可以在连接到MongoDB时附加记录器,然后发布日志输出的相关部分吗?