Rails form_tag 路由到非 Restful 动作,不包含浏览器 url 中的动作名称

Rails form_tag routing to non-Restful action without including name of action in url on the browser

我在 index.html.erb 中有一个 form_tag,它必须路由到一个操作 update_multiple 以使用表单中的选择更新数据库。但是有多个问题都与形式和路线相互关联。

问题 1:尽管在 form_tag 中明确给出了操作和方法作为 PUT,但它采用 _method 作为删除并继续销毁操作。我不确定索引表是否不采取非 restful 操作。

点击提交后的错误是:

{"utf8"=>"✓","_method"=>"delete","authenticity_token"=>"e/NgCpW+PQ==","true"=>"{:value=>nil}","false"=>"{:value=>nil}","cv_attachment_id"=>"33","commit"=>"Select Main","user_id"=>"97","id"=>"update_multiple"}

cv_attachment_id 是所选记录的,但最后一个 ID 是什么,正常操作应该是什么,什么是 true 和 false,它们都设置为 nil?

表单代码在index.html.erb

<%= form_tag update_multiple_user_cv_attachments_path, method: :put, action: :update_multiple do %>
      <table class="table table-bordered table-striped">
        <thead>
          <tr>
            <th> Select a CV </th>
            <th> Resume Name </th>
            <th> Creation Date </th>
            <th> Delete Resume </th>
          </tr>
        </thead>
        <tbody>
        <% @cv_attachments.each do |cv_attachment| %>
        <%= hidden_field_tag cv_attachment.main, :value => params[:main] %>
          <tr>
            <td><%= radio_button_tag "cv_attachment_ids[]", cv_attachment.id, cv_attachment.main %> </td>
            <td><%= cv_attachment.attachment.file.basename %></td>
            <td><%= cv_attachment.posting_date %></td>
            <td><%= button_to "Delete", user_cv_attachment_path(current_user, cv_attachment), method: "delete", data: { confirm: 'Are you sure?' }, class: "btn btn-danger btn-outline btn-md" %></td>
          </tr>
        <% end %>
        </tbody>
      </table>
      <br>
      <%= submit_tag "Select Main", :class =>'button' %>
     <% end %>

routes.rb

#resources :cv_attachments, only: [:index, :show, :edit, :create, :new, :destroy,]

resources :cv_attachments do
  collection do
    put 'update_multiple'
  end
end

问题 2:如您所见,我为 Restful 和非 restful 操作指定了 2 cv_attachments,因为它搞砸了路线,我不得不评论 Restful 一个那么如何同时拥有它们。

问题 3:同样通过收集并在点击提交后将 update_multiple 添加到 url 的末尾,例如:

http://localhost:3000/users/97/cv_attachments/update_multiple

但我不想要 url 中的操作名称:http://localhost:3000/users/97/cv_attachments

我倾向于在用户上创建一个成员路由。

路线

 resources :users do
  member do
    post :update_main_attachment
  end
end

形式

<%= form_tag update_main_attachment_user_path do %>
  <thead></thead>
  <tbody>
    <% @cv_attachments.each do |cv_attachment| %>
      <% if cv_attachment.main %>
        <%= hidden_field_tag "ex_main_cv", cv_attachment.id %>
      <% end %>
      <tr>
        <td><%= radio_button_tag "main_cv", cv_attachment.id, cv_attachment.main %> </td>
        <td><%= cv_attachment.attachment.file.basename %></td>
      </tr>
    <% end %>
  </tbody>
<% end %>

为了回答你的第二个问题,你可以在 resourceful routes 下嵌套 collection routes:

resources :cv_attachments, only: [:index, :show, :edit, :create, :new, :destroy,] do
  collection do
    put 'update_multiple'
  end
end

对于第 3 期,您可以使用 :as 选项为收集路线命名。参考the Rails docs.

@Margo 再次感谢,因为我已经接受了你的意见。我弄清楚了为什么表单会销毁而不是更新。实际上有一个 button_to 用于删除附件,当我更改为 link_to 时,表单就转到了正确的控制器 method.And 我从来没有怀疑过一个看起来无害的按钮,它不是 'form Submit'-按钮,是罪魁祸首!

解决方法如下:routes.rb

resources :cv_attachments, only: [:index, :show, :create, :new, :destroy] do
collection do
  put 'update_multiple'
end

结束

index.html--只给出部分表格

<tbody>
          <% @cv_attachments.each do |cv_attachment| %>
            <% if cv_attachment.main %>
                <%= hidden_field_tag "ex_main", cv_attachment.id %>
            <% end %>
            <tr>
              <td><%= radio_button_tag "new_main", cv_attachment.id, cv_attachment.main, :id => "#{cv_attachment.id}"%> </td>
              <td><%= cv_attachment.attachment.file.basename %></td>
              <td><%= cv_attachment.posting_date %></td>
              <td><%= link_to "Delete", user_cv_attachment_path(current_user, cv_attachment), method: "delete", data: { confirm: 'Are you sure?' }, class: "btn btn-danger btn-outline btn-md" %></td>
            </tr>
          <% end %>
        </tbody>

控制器:

def update_multiple
if request.put?
  if params["ex_main"] != params["new_main"]
    CvAttachment.find(params[:ex_main]).toggle!(:main)
    CvAttachment.find(params[:new_main]).toggle!(:main)
  end
end