Rails 4 / Rack 忽略 _method override 参数

Rails 4 / Rack disregarding _method override parameter

我有一个 Rails 4 具有浅嵌套路由的应用程序:

  resources :funds do
    resources :fund_mappings, shallow: true
  end

我理解 PATCH /fund_mappings/(:id) 应该匹配 FundMappingController#update 因为路由很浅(所以只有 newcreate 的路由实际上包含 /fund/在开头)。实际上,这条路线列在 rake:routes:

的输出中
PATCH   /fund_mappings/:id(.:format)    fund_mappings#update

当然,浏览器并不能真正使用 PUT、PATCH 或 DELETE,所以 Rack 中有一个 hack(我相信)应该将 HTTP 方法换成 _method HTTP 参数的内容。

所以当我去更新记录时得到这个错误:

No route matches [POST] "/fund_mappings/1"

我认为我提交的表单没有值为 patch_method 字段。所以我检查了表格,有一个字段具有该值。此外,Rails 错误页面表明它顺利通过:

{
 "utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"stuff",
 "fund_mapping"=> {
   "key"=>"asdf",
   "source_id"=>"1"
 },
 "commit"=>"Save"
}

那么为什么 Rails(或 Rack)认为这是一个 POST 请求?

事实证明,在我的 Gemfile 中包含 gem rails-api 导致了这个问题。我的应用程序有一个 API 部分,还有一个人为 UI 部分,所以我创建了一个 ApiController 继承自 ActionController::API(来自 gem)对于 API 的东西。另外,我有一个 ApplicationController 继承自 ActionController::Base 就像正常的人类 UI 一样。我以为 rails-api 相关的东西会被限制在 ApiController 中——事实证明这是错误的。

rails-apirails 并不意味着共存,如果你尝试它会破坏很多东西。但是,如果您设置应用程序的 config.api_only = false(默认情况下为 true),则它不会破坏这部分。

rails-api 中这两行的组合导致了这个问题:

setting config.api_only = true

don't include Rack::MethodOverride in the middleware stack for the application if config.api_only = true