まず、RSpec3でのAnonymous controller変更点について触れる。
従来Anonymous controllerはBaseClassを指定しない状態で定義すると必ずApplicationControllerのSubClassとして定義されていた。
RSpec3以降指定しない状態だとdescribe_classをBaseClassとして用いるようになった。
describe HogesController do controller do end end
この場合controllerはHogesControllerのSubClassとして定義される。
設定によってこの挙動を従来の挙動に戻すことも可能。詳しくは下記参照。
rspec-rails/anonymous_controller.feature at master · rspec/rspec-rails · GitHub
で、何があったかというとroutes.rbの設定でhogesのroutingを少々変更していた。
resources :hoges, param: :homu
単一のリソースに対しての処理を行う際通常:idをパラメータとして受け取り処理するが:homuに変更していた。
実際に遭遇していたのがupdateなのでupdateで書くと生成されるroutingは下記。
- PATCH /hoges/:homu
RSpecでリクエストをする時はこんなように書けば良い。
patch :update, homu: 1
でこの部分のテストにAnonymous controllerを使ったテストを書いた。
describe HogesController do controller do def update # なんか処理! end end describe 'PATCH#update' do before do patch :update, homu: 1 end it { expect(response.status).to eq(200) } end end
なんかリクエスト成功した!みたいな比較的どうでもいいことをしたかったのだが、これがno route matchになって混乱した。
{controller: :hoges, action: :update, homu: 1}
ってなってるし正しそうだけどno route match。
アプリ側の動作は問題ないのでRSpec側のみ起きてることは分かった。
homuをidに変えてみるとリクエストすることができたのでroutesの変更が効いてない?
homuに戻してAnonymous controllerの記述を消してみるとリクエストに成功した。
Anonymous controllerがroutes.rbの変更による影響を受けないroutesを使用しているという推測を立ててそれっぽい話題を探す。
To clarify the application routes are available to the controller when it runs. It is the custom anonymous controller routes which are not.
Anonymous controller can't access application routes · Issue #1321 · rspec/rspec-rails · GitHub
application routesというのがアプリ側のroutingのことだと思うがanonymous controllerはそうではないと言っている(と思うんだけど英語わかんねえこれ
動作がそうなっていてそれっぽい情報も得たけど気持ち悪いのであとでもう少し調べる。