2015-12-02 97 views
2

好吧,PATCH和PUT路線升級

我在提升我們的Rails Rails中3.2 3應用程序的中間是到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


這是我們所看到的行爲:

  • PUT測試失敗on Rails的4,因爲沒有404升至
  • PATCH測試成功
  • PUT要求適用於生產
  • PATCH請求生產失敗

我們理解這一點的方式與文檔不符。該表單正在生成適當的PATCH請求,但我們無法在RSpec測試中獲得正確的行爲。

,我們期待什麼:

  • PUT提高404
  • PATCH成功

寶石使用: * Rails的4.2 * RSpec的3.4 * RSpec的護欄3.4 * simple_form 3.2

回答

3

控制器特殊c假整個請求週期。該請求從不會真正觸及路由層 - 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 
+0

是的,我只是瀏覽整個rails文檔關於路由,它明確寫在那裏''get'方法,他們根本沒有被檢查。這是非常混亂..... –

+1

它看起來更有意義,如果你看[ActionController :: TestCase](https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case .rb),它並沒有真正創建一個http請求,只是模擬一個應用程序並使用它來實例化控制器。這可以讓你以不可能的方式插入控制器內部。如果你真的想通過HTTP訪問Rails棧,你可以使用[request spec](https://www.relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec)。 – max