Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 4 RubyonRails选择错误的控制器操作_Ruby On Rails 4_Rails Routing - Fatal编程技术网

Ruby on rails 4 RubyonRails选择错误的控制器操作

Ruby on rails 4 RubyonRails选择错误的控制器操作,ruby-on-rails-4,rails-routing,Ruby On Rails 4,Rails Routing,今天,我遇到了一些奇怪的(而且非常不方便的)RubyonRails行为,即使对网络进行持续的梳理,也不能给出令人满意的答案。 注意:我翻译了方法和路由名称,以便用英语更容易阅读,希望没有引入任何不一致之处 处境 环境 RubyonRails4.2.0在Ruby2.0下执行(也在Ruby2.2.0下测试) 相关代码 考虑具有以下操作的控制器: class AssignmentsController < ApplicationController def update ...

今天,我遇到了一些奇怪的(而且非常不方便的)RubyonRails行为,即使对网络进行持续的梳理,也不能给出令人满意的答案。 注意:我翻译了方法和路由名称,以便用英语更容易阅读,希望没有引入任何不一致之处

处境 环境 RubyonRails4.2.0在Ruby2.0下执行(也在Ruby2.2.0下测试)

相关代码 考虑具有以下操作的控制器:

class AssignmentsController < ApplicationController
  def update
    ...
  end

  def takeover_confirmation
    ...
  end
end
rake路由的相关输出

assignment POST  /assignments/:id(.:format)  assignments#update
assignments_takeover_confirmation  POST  /assignments/takeover_confirmation(.:format) assignments#takeover_confirmation
...
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
....
问题 当我向
assignments\u takeover\u confirmation\u路径发布帖子时,rails将其路由到
update
方法。服务器日志:

Started POST "/assignments/takeover_confirmation" for ::1 at ...
Processing by AssignmentsController#update as HTML
缓解 如果我将
更新
路由定义放在
接管确认
之后,它将按预期工作(但没有检查
更新
的帖子)

此外,在写了所有这些之后,我发现我在routes.rb(POST而不是PATCH)中对
update
方法使用了错误的请求类型。在routes.rb中执行此操作确实解决了我的问题:

patch 'assignments/:id' => 'assignments#update', as: 'assignment'
但是,即使将其定义为POST,Rails也不应该将POST请求指向现有路径“/assignments/takeover\u confirmation”,指向完全不同的操作,是吗? 我担心下次我为同一个控制器使用两个POST路由时,它会再次执行相同的操作

似乎我对铁路路线有着严重的误解,但我不能对此指手画脚

编辑:解决方案 正如katafrakt所解释的,上面对
/assignments/takeover\u confirmation
的请求与路径
assignments/:id
匹配,因为Rails将“takeover\u confirmation”部分解释为字符串,并将其用于:id参数。因此,这是完全可以预期的行为

工作示例 为了完整起见,以下是一个可行的(如果是最低限度的)路线定义,该定义受到Chris评论的启发:

  resources :assignments do
    collection do
      post 'takeover_confirmation'
    end
  end
在本例中,仅显式定义了手动创建的路由。更新、显示等路由(我最初手动定义)现在由
resources::assignments
隐式定义

相应摘录自《rake routes》

assignment POST  /assignments/:id(.:format)  assignments#update
assignments_takeover_confirmation  POST  /assignments/takeover_confirmation(.:format) assignments#takeover_confirmation
...
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\u confirmation”,指向完全不同的操作,是吗

应该这样。Rails路由的匹配顺序与
routes.rb
文件中定义的顺序完全相同(从上到下)。因此,如果它匹配某个规则(并且
/assignments/takeover\u confirmation
匹配
assignments/:id
规则),它将停止处理路由

这种行为简单而有效。我想,任何一种“智能”匹配最佳路线都会导致麻烦和意外的结果


顺便说一句,这就是为什么过去在路由文件的最底部定义了“捕获所有路由”的原因。

也许我在阅读您的问题时遗漏了一些内容,但您为什么不在路由文件中使用
资源。。。哦,我看到你使用了很多手动定义的路线。那么,当您使用
资源时会发生什么?你得到你想要的行为了吗?现在尝试重构它。。。将让你知道它是如何运作的。谢谢你的评论。我编辑了“解决方案”部分,并根据您的建议在那里放置了一个工作示例。啊!我甚至从来没有想过,您可以将字符串“takeover\u confirmation”解释为一个参数,并将其传递为:id。事实上,这正是后来发生的事情,当我的更新方法中的行
Assignment.find params[:id]
抱怨找不到id为“takeover\u confirmation”的对象时。因此,这样匹配路线是正确的——我只是没有看到它!您可以使用约束来避免这种情况。像
post'assignments/:id'=>'assignments#update',as'assignment',constraints:{id:/\d.+/}
。谢谢,我不知道这一点,在类似的情况下它可能会派上用场。然而,我认为首先避免这种模棱两可的做法更为明智——毕竟,在你解释了为什么会发生这种情况之后,这并没有问题。