今天,我遇到了一些奇怪的(非常不便)的Ruby on Rails行为,即使持续地对网络进行梳理也无法得出令人满意的答案。注意:我翻译了方法和路线名称,以英语更容易阅读,希望我不会引入任何不一致之处。
在Ruby 2.0下执行的Ruby on Rails 4.2.0(也在Ruby 2.2.0下进行了测试)
考虑采取以下措施的控制器:
class AssignmentsController < ApplicationController
def update
...
end
def takeover_confirmation
...
end
end
由于我使用了许多手动定义的路由,因此没有使用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
当我对进行POST时assignments_takeover_confirmation_path
,rails会将其路由到update
方法。服务器日志:
Started POST "/assignments/takeover_confirmation" for ::1 at ...
Processing by AssignmentsController#update as HTML
如果我把update
路由定义后的takeover_confirmation
一个,它按预期工作(没有检查的支撑柱,update
虽然)。
此外,写完所有这些内容后,我发现我update
在route.rb中使用了错误的请求类型(POST而不是PATCH)。在routes.rb中这样做确实可以解决我的问题:
patch 'assignments/:id' => 'assignments#update', as: 'assignment'
但是,即使将其定义为POST,Rails也不应将POST请求定向到现有路径“ / assignments / takeover_confirmation”的完全不同的操作,应该吗?我担心下次我对同一控制器使用两个POST路由时,它将再次执行相同的操作。
似乎我对Rails路由有严重的误解,但不能对此付诸行动...
正如katafrakt所解释的,上述请求/assignments/takeover_confirmation
与路由匹配是assignments/:id
因为Rails将“ takeover_confirmation”部分解释为字符串并将其用于:id参数。因此,这是完全可以预期的行为。
为了完整起见,这是一个可行的(如果是极简的)路由定义,它的工作受到了克里斯的评论的启发:
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
....
谢谢您的帮助!
但是,即使将其定义为POST,Rails也不应将POST请求定向到现有路径“ / assignments / takeover_confirmation”的完全不同的操作,应该吗?
这应该。Rails路由的匹配顺序与routes.rb
文件中定义的顺序完全相同(从上到下)。因此,如果它与某个规则/assignments/takeover_confirmation
匹配(并且与assignments/:id
规则匹配),它将停止处理路由。
此行为简单有效。我认为匹配最佳路线的任何一种“智能”都会导致麻烦而出乎意料的结果。
顺便说一句,这就是为什么以前在路由文件的最底部定义了全部路由的原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句