Rails 升级中的 PATCH 和 PUT 路由

PATCH & PUT routes in Rails upgrade

好的,

我正在将我们的 Rails 3 应用程序从 Rails 3.2 升级到 Rails 4.2。阅读升级说明和更改后,我们 运行 遇到了一些 PUTPATCH 路由的奇怪问题。

在我们的 Rails 3 应用程序中,我们定义了以下路由:

resources :entities, except: [:show] do
  member do
    put :change_monitoring_status
  end
 end

当 运行 rake routes 时,change_monitoring_status 路由显示为正确的 PUT 路由。使用 Rails 助手为此生成的表单在 Rails 3.

中生成正确的请求

然而,在 Rails 4 中,此表单现在生成 PATCH 路由。这完全没问题,因为现在这是 Rails 中的标准行为。但是,当我们在 Rails 4 Production 上使用表格时,这会导致 404 - Not Found.

我们尝试为此编写一个 RSpec 测试来模拟相同的行为并关闭错误票。所以对于我们的 Rails 4 升级,我们编写了以下测试:

describe '#change_monitoring_status' do

  before(:each) do
    sign_in user
  end

  it 'fails when put is used' do
    expect {
      put :change_monitoring_status, id: entity.id, _method: "PUT", form_object: {  }
    }.to raise_error
  end

  it 'works when patch is used' do
    expect {
      patch :change_monitoring_status, id: supplier.id, _method: "PATCH", form_object: {  }
    }.to_not raise_error
  end
end

我们还将路线更改为 PATCH 而不是现在的 PUT


这是我们看到的行为:

我们的理解方式与文档不符。表单正在生成正确的 PATCH 请求,但我们无法在 RSpec 测试中获得正确的行为。

我们的期望:

使用的宝石: * Rails 4.2 * RSpec 3.4 * RSpec-rails 3.4 * simple_form 3.2

控制器规范伪造整个请求周期。请求从未真正到达路由层 - RSpec 只是在路由文件中查找与控制器和操作匹配的路由。

虽然这对速度有好处,因为您跳过了整个机架层,但它有时会掩盖路由错误。

您的规格也略有不同;第一个使用 id: entity.id 而后者使用 id: supplier.id.

在这种情况下,我会使用 routing spec 或请求规范,因为这会在路由层中导致错误 - 在控制器匹配之前。

describe "change_monitoring_status", type: :routing do

  it 'fails when put is used' do
    expect(puts: "/entity/37/change_monitoring_status").not_to be_routable
  end

  it 'works when patch is used' do
    expect(patch: "/entity/37/change_monitoring_status").to 
      route_to(
         controller: "entities", 
         action: "change_monitoring_status", 
         id: 37
      )
  end
end