Rails Restful动作索引Put

7

我经常遇到一种情况,即想要一次性更新多条记录,就像GMail设置多个邮件为“已读”或“未读”一样。

Rails鼓励使用ActiveRecord类上的“update”方法 - Comment.update(keys, values)

例如 - http://snippets.dzone.com/posts/show/7495

这是非常好的功能,但很难映射到restful路由。 从某种意义上说,我希望在集合上看到一个:put操作。 在路由中,我们可以添加类似以下内容的东西:

map.resources :comments, :collection => { :update_many => :put }

在表单中,你需要这样做...
<% form_for @comments do |f| %>
  ...

这种方法存在多个问题。如果你这样写::collection => { :update_many => :put },Rails会向索引操作(CommentsController#index)提交POST请求,而我希望它能够发送到“update_many”操作。相反,你可以这样写::collection => { :update_many => :post }。这样至少能够在控制器中调用正确的操作。
另外,你需要使用以下代码替换<% form for @comments ...:
<% form_for :comments, :url => { :controller => :comments, :action => :update_many } do |f| %>

这种方式可以正常工作。

但依旧不完美 - 感觉有点不按照Rails的方式来做。在集合控制器上,:post和:delete也似乎是有意义的。

我在此发帖,想看看是否有任何遗漏的设置。对于如何以RESTful的方式进行集合级别的:post、:put、:delete,还有其他想法吗?


我意识到我的回答只是提供了另一种解决你问题的方法。我已经编辑过来反映这一点。 - EmFi
2个回答

2
我遇到过你描述的几种情况。前几次我实现的表单与你建议的几乎相同。
第三次遇到这个问题时,我意识到我正在更新的每个项目都与其他某些事物有共同的belongs_to关系。通常是一个用户。这正是你需要理清RESTful的顿悟。它还将帮助您清理表单/控制器。
不要把它看作是更新一堆消息,而是更新一个用户。
以下是我过去使用的一些示例代码,以突出区别。假设我们想在当前用户所属的消息上执行批量操作...
截至Rails 2.3,我们可以添加
 accepts_nested_attributes_for :messages

针对用户模型进行操作。确保messages_attributes是attr_accessible的一部分,或者不是attr_protected的。

然后创建路由:

 map.resources :users, :member => {:bulk_message_update, :method => :put}

然后将该操作添加到控制器中。具备 AJAX 功能 ;)
 def bulk_message_update
   @user = User.find(params[:id])
   @user.update_attributes(params[:user])
   if @user.save 
     respond_to do |format|
       format.html {redirect}
       format.js {render :update do |page|
          ...
       } 
     end       
   else
     ....
 end 

然后你的表单会变成这个样子:
<% form_for current_user, bulk_message_update_user_url(current_user), 
     :html => {:method => :put} do |f| %>
  <% f.fields_for :messages do |message| %>
    form for each message
  <% end %>
  <%= sumbit_tag %>
<% end %>

1
如果messages是user的子资源,那么将PUT请求发送到/user/123/messages似乎更合适。你觉得呢? - John Bachir

1

我经常在一个本来符合RESTful标准的控制器中添加基于集合的update_multiple和destroy_multiple操作。

看看这个Railscast关于通过复选框进行更新的视频教程。它应该能够给你一个很好的思路,如果你遇到问题,请回来并在这个问题上继续添加!


谢谢,看起来使用 'form_for' 与 :put 操作不起作用。当我切换到 'form_tag'(如 Ryan B. 所演示的那样),它现在转到正确的操作并正常工作。我没有试图弄清楚为什么。有一件小事 - 我喜欢使用 'fields_for' 块为每个记录生成输入字段(f.text_field)。Ryan 在他的视频中没有使用 fields_for(可能是因为它早于 helper),而是使用 _tag 方法。在这里使用 'fields_for' 是可以的。 - Mark Swardstrom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接