【发布时间】:2023-03-21 13:20:02
【问题描述】:
今天我遇到了一些奇怪(而且非常不方便)的 Ruby on Rails 行为,即使是对网络的持续梳理也没有产生令人满意的答案。 注意:我将方法和路由名称翻译成英文更容易阅读,希望我没有引入任何不一致的地方。
情况
环境
Ruby on Rails 4.2.0 在 Ruby 2.0 下执行(也在 Ruby 2.2.0 下测试)
相关代码
考虑一个具有这些操作的控制器,以及其他:
class AssignmentsController < ApplicationController
def update
...
end
def takeover_confirmation
...
end
end
routes.rb
由于我使用了很多手动定义的路由,我确实没有使用 routes.rb 中的资源。有问题的路线定义如下:
...
post 'assignments/:id' => 'assignments#update', as: 'assignment'
post 'assignments/takeover_confirmation' => 'assignments#takeover_confirmation'
...
rake routes的相关输出:
assignment POST /assignments/:id(.:format) assignments#update
assignments_takeover_confirmation POST /assignments/takeover_confirmation(.:format) assignments#takeover_confirmation
问题
当我对 assignments_takeover_confirmation_path 进行 POST 时,rails 会将其路由到 update 方法。服务器日志:
Started POST "/assignments/takeover_confirmation" for ::1 at ...
Processing by AssignmentsController#update as HTML
缓解
如果我将update 路由定义放在 takeover_confirmation 之一之后,它会按预期工作(虽然没有检查到update 的POST)。
此外,在写完所有这些之后,我发现我在 routes.rb 中为 update 方法使用了错误的请求类型(POST 而不是 PATCH)。在 routes.rb 中这样做确实解决了我的问题:
patch 'assignments/:id' => 'assignments#update', as: 'assignment'
但是,即使将其定义为 POST,Rails 也不应该将针对现有路径“/assignments/takeover_confirmation”的 POST 请求定向到完全不同的操作,不是吗? 我担心下次我为同一个控制器使用两个 POST 路由时,它会再次做同样的事情。
看来我对 Rails 路由有一个严重的误解,但我不能指手画脚......
编辑:解决方案
正如 katafrakt 所解释的,上述对/assignments/takeover_confirmation 的请求与路由assignments/:id 匹配,因为Rails 将“takeover_confirmation”部分解释为字符串并将其用于:id 参数。因此,这是完全可以预料的行为。
工作示例
为了完整起见,受 Chris 的评论启发,这是一个可行的(如果是简约的)路由定义:
resources :assignments do
collection do
post 'takeover_confirmation'
end
end
在这个例子中,只有我手动创建的路由是明确定义的。更新、显示等(我一开始手动定义的)路由现在由resources: :assignments 隐式定义。
来自rake routes的相应摘录:
...
takeover_confirmation_assignments POST /assignments/takeover_confirmation(.:format) assignments#takeover_confirmation
...
assignment GET /assignments/:id(.:format) assignments#show
PATCH /assignments/:id(.:format) assignments#update
PUT /assignments/:id(.:format) assignments#update
DELETE /assignments/:id(.:format) assignments#destroy
....
感谢您的帮助!
【问题讨论】:
-
也许我在阅读你的问题时错过了一些东西,但你为什么不在你的路线文件中使用
resources? ...哦,我看到您使用了很多手动定义的路线。那么当你使用resources时会发生什么?你得到你想要的行为了吗? -
现在尝试重构...会让你知道结果如何。
-
感谢您的评论。我根据您的建议编辑了“解决方案”部分并在其中放置了一个工作示例。
标签: ruby-on-rails-4 rails-routing