いや〜ハマったハマった。 rails-api っていうフルスタックのRailsからAPIに特化した構成に削ぎ落としてくれるGemがあるんだけど、これで「何が削られているのか」をちゃんと把握してないとハマる。
基本的なRailsアプリとrails-api の Middleware 比較
rake タスクを実行すれば見れる。
フルスタック
$ bundle exec rake middleware use ActionDispatch::Static use Rack::Lock use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fe29f9cc6e0> use Rack::Runtime use Rack::MethodOverride use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use BetterErrors::Middleware use ActionDispatch::RemoteIp use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore use ActionDispatch::Flash use ActionDispatch::ParamsParser use Rack::Head use Rack::ConditionalGet use Rack::ETag run MyApp::Application.routes
rails-api
use ActionDispatch::Static use Rack::Lock use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fac42102e08> use Rack::Runtime use ActionDispatch::RequestId use Rails::Rack::Logger use ActionDispatch::ShowExceptions use ActionDispatch::DebugExceptions use ActionDispatch::RemoteIp use ActionDispatch::Reloader use ActionDispatch::Callbacks use ActionDispatch::ParamsParser use Rack::Head use Rack::ConditionalGet use Rack::ETag run MyApp::Application.routes
今回ハマったのは use Rack::MethodOverride
。これは putとかpatchとかのリクエスト送るときにformのmethodは"post”にしておいて、hiddenパラメータで_method="patch"
ってのを指定することで擬似的にPATCHリクエストを実現するための仕組み。
なんと、rails-apiではデフォルトではこのRack::MethodOverrideが搭載されていないのだ。
てことで config/application.rb に
config.middleware.use Rack::MethodOverride
を追加して解決した。
今回自分がやりたかったのは、作ったAPIを実験するためのhtml集を作っていて(もちろんテストコードも書いてます)、そこで _methodをpatchにしても全部 post として解釈されてしまって3時間くらいハマった。