我正在使用 Mongoid 的 recursively_embeds_many 创建嵌套数据树(Rails 3.2.8、Mongo 2.2、Mongoid 3.0.14 和 Ryan Bates 的 nested_form gem 0.3.1)。到目前为止一切都顺利进行,但我遇到了一个障碍,我似乎无法摆脱它,特别是如何重新排序生成的数组成员。我有一些 JS 可以帮助我在前端操作表单,但我无法弄清楚在后端表示的新订单。这是我的主要模型:
class Navigator
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :menu_items
accepts_nested_attributes_for :menu_items, :allow_destroy => true, :autosave => true
field :name
field :type
field :position
field :behavior
end
这是 MenuItems 模型:
class MenuItem
include Mongoid::Document
include Mongoid::Timestamps
recursively_embeds_many
accepts_nested_attributes_for :child_menu_items, :allow_destroy => true, :autosave => true
field :name
field :url
end
观察服务器,我可以看到当前发生的情况是,在更新期间,通过该$push_all
方法添加新项目,并通过匹配嵌套数组方法的 $ 位置运算符更新其他项目(这看起来是Mongoid对JIRA SERVER的实现-851 解决方法)。因此,每个 menu_item 的位置始终根据其输入位置而固定。我知道我可以添加任意数量的排序属性和策略,但这在 Mongo 中似乎没有必要,因为可以让数组的顺序代表用户强加给它的顺序。
我知道 Mongo 有上述限制,但每次更新数组时覆盖它似乎也是合理的,换句话说,使用 Mongo 的$set
运算符替换该数组的现有内容。但是,我不知道如何用 Mongoid 做到这一点。我希望它可以像切换我的控制器一样简单
@tree.update_attributes(params[:tree])
至
@tree.set(params[:tree])
这会导致查询格式正确,但完全转义。然后我想也许我可以$unset
先输入该字段,然后删除表单中隐藏的 id 字段,但这也失败了。
在我看来,这是 Mongo 的规范用例,但 Mongoid 也阻止我以 Mongo-y 方式更新文档。我也知道 Mongoid 能够使用$set
运算符,因为它习惯于覆盖updated_at
由于使用时间戳而添加的属性。如果我可以将 Mongoid 配置为简单地使用$set
操作符进行更新,而不是使用 $ 位置操作符解决方法,我会被设置。我是在考虑错误的方式还是遗漏了什么?我的下一步是尝试直接逃到 Mongo 驱动程序中。
谢谢,卡尔
更新:
@tree.update_attribute(:tree, params[:tree])
创建正确的轻便摩托车输出,但数据没有得到更新。即使我更改了与修改数组无关的内容。
更新:
虽然我无法找到 Mongoid 解决方案,但我能够找到一个 jQuery 解决方案:在使用 jQuery UI 排序之后,我已经在使用它来重命名数组键,所以我添加了一些东西以备不时之需。我制作了所有项目的副本,将现有项目设置为删除,然后添加副本,就好像它们是新的一样。提交表单后,首先删除所有旧的,然后按照页面上的顺序将所有副本添加为新的。这不是一个理想的解决方案,但它运行良好,而且我对所有技术的精神感觉良好 - 表单仍在一次处理中,我不需要在任何模型上添加外部排序属性。如果关闭了 JS 它将无法工作,但拖放排序也不会。