好,
我正在将Rails 3应用程序从Rails 3.2升级到Rails 4.2。在阅读升级说明和更改后,我们遇到了一些PUT
和PATCH
路由的奇怪问题。
在我们的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
。
这是我们看到的行为:
PUT
测试失败,因为没有引发404 PATCH
测试成功PUT
请求适用于制作PATCH
请求生产失败我们理解这一点的方式与文档不符。该表单正在生成一个正确的PATCH
请求,但我们无法在RSpec测试中获得正确的行为。
我们的期望:
PUT
筹集404 PATCH
成功使用的宝石: * Rails 4.2 * RSpec 3.4 * RSpec-rails 3.4 * simple_form 3.2
答案 0 :(得分:3)
控制器规范假冒整个请求周期。请求永远不会真正到达路由层 - RSpec只在路由文件中查找与控制器和操作匹配的路由。
虽然这对速度有好处,因为你跳过整个Rack层,它有时会掩盖路由错误。
您的规格也略有不同;第一个使用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