nested_form gem 添加有效但删除失败...为什么?
我正在使用来自 GitHub 的 Ryan Bates 的nested_form gem 的 madebydna 版本(可以在 https://github.com 找到/madebydna/nested_form)。我使用分叉版本来支持 jQuery,而不是 Prototype。
更新: 检查页面底部是否有此问题的更新。
编辑:
我正在使用:RoR v3.0.5,jQuery v1.4.3,Ruby v1.9.2
结束编辑
编辑: 至少从我在其他网站上看到的情况来看,传递到服务器的 pictures_attributes 参数的当前结构似乎导致了问题。当前发送的结构如下:
"pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"5"}}
我见过的所有其他网站,图片属性错误具有以下结构:
"pictures_attributes"=>[{"_destroy"=>"1", "id"=>"5"}]
我不确定如何更改我的代码以使其发生后者,而不是前者。想法?
结束编辑
我按照 T 的指示进行操作,添加链接非常适合添加嵌套模型,但删除失败。换句话说,我可以为特定模型添加多个字段,并且在提交表单时创建并保存这些模型,但是当我再次编辑同一记录并删除我刚刚创建的嵌套模型时,它们会失败从相关记录中删除。
这是安装nested_form gem 后生成的nested_form.js 脚本。请原谅,但我创建了一个 Pastie 并减少了它: http://bit.ly/ge5BO7
这是相关的模型代码:
has_many :pictures, :as => :imageable, :dependent => :destroy
accepts_nested_attributes_for :pictures, :allow_destroy => true, :reject_if => lambda { |a| a[:photo].blank? }
这是视图代码(在 _form.html.erb 部分中):
<div id="picture_fields">
<% f.fields_for :pictures do |pics| %>
<div class="field">
<%= pics.label :photo, "Photo" %>
<%= pics.file_field :photo %>
<%= pics.link_to_remove "Remove Photo" %>
</div>
<% end %>
<p>
<%= f.link_to_add "Add Photo", :pictures %>
</p>
这是为一个字段生成的 HTML:
<div class="fields">
<div class="field">
<label for="equipment_pictures_attributes_0_photo">Photo</label>
<input id="equipment_pictures_attributes_0_photo" name="equipment[pictures_attributes][0][photo]" type="file">
<input id="equipment_pictures_attributes_0__destroy" name="equipment[pictures_attributes][0][_destroy]" type="hidden" value="false">
<a href="javascript:void(0)" class="remove_nested_fields">Remove Photo</a>
</div>
<input id="equipment_pictures_attributes_0_id" name="equipment[pictures_attributes][0][id]" type="hidden" value="5">
</div>
这是提交表单时生成的日志条目:
Started POST "/equipment/494882120" for <ipadd deleted> at 2011-03-24 13:04:18 -0400
Processing by EquipmentController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"98/R6EYCAFd6HwBjMV6bhnfRo6cT7NqPZ9fJ/VEOKKE=", "equipment"=>{"location_id"=>"", "model"=>"fasdf", "serial_number"=>"", "unh_id"=>"", "doc_id"=>"", "purchase_price"=>"", "date_acquired(1i)"=>"2011", "date_acquired(2i)"=>"3", "date_acquired(3i)"=>"24", "comment"=>"", "vendor_id"=>"", "new_vendor_name"=>"", "department_id"=>"320903175", "new_department_name"=>"", "activity_id"=>"", "new_activity_code"=>"", "condition_id"=>"746868371", "new_condition_name"=>"", "pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"5"}}}, "commit"=>"Update Equipment", "id"=>"494882120"}
Equipment Load (0.7ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."id" = 494882120 LIMIT 1
Picture Load (0.4ms) SELECT "pictures".* FROM "pictures" WHERE "pictures"."id" IN (5) AND ("pictures".imageable_id = 494882120 AND "pictures".imageable_type = 'Equipment')
DEPRECATION WARNING: Overwriting validate in your models has been deprecated, please use Base#validate :method_name instead. (called from block in update at /opt/intranet3-dev/app/controllers/equipment_controller.rb:63)
Department Load (0.1ms) SELECT "departments".* FROM "departments" WHERE "departments"."id" = 320903175 LIMIT 1
Condition Load (0.1ms) SELECT "conditions".* FROM "conditions" WHERE "conditions"."id" = 746868371 LIMIT 1
现在,就我而言,我覆盖我的所有基础,允许在 _destroy => 时销毁嵌套对象提交的参数中遇到“1”。然而,该物体显然没有被破坏。是不是参数提交给服务器的方式有问题?
希望比我更敏锐的人能看到一些明显的错误。帮助!
更新:
好的,我已经通过从accepts_nested_attributes_for 语句中删除 :reject_if 子句来解决这个问题。如果您有上传文件表单,这是一个边缘案例,我敢称其为错误。
就我而言,我能够将照片附加到我的设备模型中,并且在编辑时会渲染表单,使得我附加到记录中的每张照片的文件字段为空白(这是应该发生的情况)。在花费了几个小时的时间后,我思考 :reject_if 子句是否导致控制器操作完全忽略嵌套记录,即使我告诉它销毁该记录。嗯,确实如此。
如果您有 :reject_if 子句,再加上 :allow_destroy =>; true,如果 :reject_if 的计算结果为 true,那么无论如何,您的记录都不会被破坏
我目前正在尝试找出一种保留 :reject_if 功能的方法。
干杯, 莱斯。
I'm using the madebydna version of Ryan Bates' nested_form gem from GitHub (can be found at https://github.com/madebydna/nested_form). I'm using the forked version for jQuery support as opposed to Prototype.
UPDATE:
Check the bottom of the page for an update to this question.
EDIT:
I'm using: RoR v3.0.5, jQuery v1.4.3, Ruby v1.9.2
END EDIT
EDIT:
It appears the current structure of the pictures_attributes parameter passed along to the server is causing an issue, at least from what I've seen on other websites. The currently sent structure is as follows:
"pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"5"}}
All other sites I've seen, the pictures_attributes error had the following structure:
"pictures_attributes"=>[{"_destroy"=>"1", "id"=>"5"}]
I'm not sure how to alter my code to make it so the latter occurs, rather than the former. Thoughts?
END EDIT
I followed the directions to a T, the add link works great for adding nested models, but remove fails. In otherwords, I can add multiple fields for a particular model, and those models get created and saved when I submit the form, but when I go to edit the same record again and go to remove the nested models which I just created, they fail to be removed from the associated record.
Here's the nested_form.js script that gets generated after installing the nested_form gem. Forgive but I created a Pastie and reduced it: http://bit.ly/ge5BO7
Here is the pertinent model code:
has_many :pictures, :as => :imageable, :dependent => :destroy
accepts_nested_attributes_for :pictures, :allow_destroy => true, :reject_if => lambda { |a| a[:photo].blank? }
Here is the view code (in the _form.html.erb partial):
<div id="picture_fields">
<% f.fields_for :pictures do |pics| %>
<div class="field">
<%= pics.label :photo, "Photo" %>
<%= pics.file_field :photo %>
<%= pics.link_to_remove "Remove Photo" %>
</div>
<% end %>
<p>
<%= f.link_to_add "Add Photo", :pictures %>
</p>
Here's the generated HTML for one field:
<div class="fields">
<div class="field">
<label for="equipment_pictures_attributes_0_photo">Photo</label>
<input id="equipment_pictures_attributes_0_photo" name="equipment[pictures_attributes][0][photo]" type="file">
<input id="equipment_pictures_attributes_0__destroy" name="equipment[pictures_attributes][0][_destroy]" type="hidden" value="false">
<a href="javascript:void(0)" class="remove_nested_fields">Remove Photo</a>
</div>
<input id="equipment_pictures_attributes_0_id" name="equipment[pictures_attributes][0][id]" type="hidden" value="5">
</div>
And here's the log entry that gets generated when submitting the form:
Started POST "/equipment/494882120" for <ipadd deleted> at 2011-03-24 13:04:18 -0400
Processing by EquipmentController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"98/R6EYCAFd6HwBjMV6bhnfRo6cT7NqPZ9fJ/VEOKKE=", "equipment"=>{"location_id"=>"", "model"=>"fasdf", "serial_number"=>"", "unh_id"=>"", "doc_id"=>"", "purchase_price"=>"", "date_acquired(1i)"=>"2011", "date_acquired(2i)"=>"3", "date_acquired(3i)"=>"24", "comment"=>"", "vendor_id"=>"", "new_vendor_name"=>"", "department_id"=>"320903175", "new_department_name"=>"", "activity_id"=>"", "new_activity_code"=>"", "condition_id"=>"746868371", "new_condition_name"=>"", "pictures_attributes"=>{"0"=>{"_destroy"=>"1", "id"=>"5"}}}, "commit"=>"Update Equipment", "id"=>"494882120"}
Equipment Load (0.7ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."id" = 494882120 LIMIT 1
Picture Load (0.4ms) SELECT "pictures".* FROM "pictures" WHERE "pictures"."id" IN (5) AND ("pictures".imageable_id = 494882120 AND "pictures".imageable_type = 'Equipment')
DEPRECATION WARNING: Overwriting validate in your models has been deprecated, please use Base#validate :method_name instead. (called from block in update at /opt/intranet3-dev/app/controllers/equipment_controller.rb:63)
Department Load (0.1ms) SELECT "departments".* FROM "departments" WHERE "departments"."id" = 320903175 LIMIT 1
Condition Load (0.1ms) SELECT "conditions".* FROM "conditions" WHERE "conditions"."id" = 746868371 LIMIT 1
Now, as far as I'm concerned I'm covering all of my bases with allowing the nested objects to be destroyed when _destroy => '1' is encountered in the submitted parameters. However, the object is clearly not being destroyed. Is there an error in the way the parameters are being submitted to the server?
Hopefully someone with a keener eye than I will see some glaring error. Help!
UPDATE:
Okay, I've managed to resolve the problem by taking out the :reject_if clause from my accepts_nested_attributes_for statement. This is a fringe case in the event you have an upload file form, and I dare call it a bug.
In my case I was able to attach photos to my Equipment model, and when editing it would render the form such that the file field was blank (which is what's supposed to happen) for every photo I have attached to my record. After plugging away at this thing for hours, I pondered if the :reject_if clause was causing the controller action to ignore the nested record entirely, even though I told it to destroy the record. Well, it does.
If you have a :reject_if clause, coupled with a :allow_destroy => true, and if the :reject_if evaluates to true YOUR RECORD WILL NOT BE DESTROYED NO MATTER WHAT
I'm currently trying to hack out a method for retaining my :reject_if functionality.
Cheers,
Les.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题在于,提交时嵌套记录的状态导致
accepts_nested_attributes_for
语句中的:reject_if
子句评估为 true,从而告诉控制器跳过并且不对它执行任何操作。因此,嵌套记录不会被破坏,因为没有对其执行任何操作。The problem is that the state of the nested record, when submitted, is causing the
:reject_if
clause in theaccepts_nested_attributes_for
statement to evaluate to true, thus telling the controller to skip over it and perform no action on it. Hence, the nested record is not destroyed since no action is performed on it.