【问题标题】:Rails, form is calling wrong actionRails,表单正在调用错误的操作
【发布时间】:2025-11-29 21:20:02
【问题描述】:

我已经制作好了表格:

      <tbody>
        <% @player.bases.each do |basis| %>
        <td><%= basis.id %></td>
        <td><%= image_tag(basis.image_url(:thumb), class: 'thumbnail') %></td>
        <td><%= link_to basis.name, basis %></td>
        <td><%= basis.cost %></td>
        <td><%= basis.short_info %></td>
        <td>
            <%= form_for @player, url: {:controller => 'players', :action => :remove_detail} do |f| %>
              <%= f.hidden_field :type, :value => 'basis' %>
              <%= f.hidden_field :detail_id, :value => basis.id %>
              <%= f.submit 'Remove',class: 'btn btn-danger' %>
            <% end %>
        </td>
        <% end %>
      </tbody>

在我的路线中,我添加了这个:

resources :players do
 collection do
   get 'search'
   post 'remove_detail'
 end
end

我的players_controller.rb 中有remove_detail,我已将此操作添加到before_action 以获取当前玩家。但是,当我按下“删除”按钮时,它会引发错误并尝试运行控制器的 update 操作。为什么?

我的before_action

before_action :set_player, only: [:show, :edit, :update, :destroy, :remove_detail]

我的remove_detail

def remove_detail
type = params['type']
id = params['detail_id']

if type == 'basis'
  basis = Basis.find(id)
  name = basis.name
  @player.bases.delete(basis)

end

redirect_to @player, notice: "#{name} detail is removed"

end

【问题讨论】:

  • 您介意发布整个模板吗?如果提供的是局部的,您能否添加一个呈现该局部的模板?

标签: ruby-on-rails ruby forms routing actioncontroller


【解决方案1】:

要解决这个问题,请尝试以下操作:

首先,我将重新定义您的路线如下:

resources :players do
  member do
    delete 'remove_detail'
  end

  collection do
    get 'search'
  end
end

这将为删除“单个Player”的detail 生成正确的url:

/players/:id/remove_detail

由于 Rails 的 REST-y 特性,我们将 url 定义为通过执行delete 请求来访问。

你的表格会相应改变:

<%= form_for @player, { url: { action: "remove_detail" }, method: :delete } do |f| %>

更改路线以使用delete 方法更符合Rails 的约定。 Post 也会让你的应用程序工作,但是 - 它只是 Rails 的方式。

祝你好运!

【讨论】:

  • 现在它给我一个错误并尝试启动我的控制器的destroy操作
  • @Mr.D,你是对的 - 我已经把代码放在我的脑海中并且犯了一个错误 - 检查更新的 sn-p 以获取 form_for。很抱歉造成混乱!
  • 效果很好。谢谢你。一个问题,你为什么在路由中做单独的成员?我可以将它添加到我的收藏中吗?我是否需要为每个新操作创建单独的成员?
  • 很高兴你来问!在为collection 定义路由时,它会生成类似:/players/remove_detail 的 url,但由于您的操作旨在修改特定的单个资源实例(在您的情况下为Player),因此声明此类路由的首选方式是@ 987654335@,它会影响像/players/:id/remove_detail 这样的网址。另一方面,您的“搜索”操作并不真正属于任何特定用户,而是在Playerscollection 上运行,因此在collection 中注册它是首选方式。在此处查看更多信息:guides.rubyonrails.org/routing.html#adding-more-restful-actions