Rails
RSpec

Rails 4系と5系で互換性のあるcontroller specを書く方法

More than 1 year has passed since last update.


環境


  • Rails v5.0.0.1

  • rspec-rails v3.5.1


前置き

Rails 4系以前と5系ではcontroller specの params の渡し方が変わっています。


Rails 4系まで

get :show, { id: 1 }


Rails 5系

get :show, params: { id: 1 }

Rails 5系で古い書き方をすると下記のようなDEPRECATION WARNINGが出ます。

DEPRECATION WARNING: ActionController::TestCase HTTP request methods will accept only keyword arguments in future Rails versions.

Examples:

get :show, params: { id: 1 }, session: { user_id: 1 }
process :update, method: :post, params: { id: 1 }

普通のアプリならメッセージに従ってspecを書き直せばいいのですが、mountable engineのようにgemの中に含まれるspecの場合はそうはいきません。

specファイルになるべく差分を発生させず、Rails 4系と5系で両方で動くcontroller specを紹介します。


やり方

params_wrapper というラッパを用意するだけです 1


spec/support/util/params_wrapper.rb

module ParamsWrapper

def params_wrapper(params = {})
if Gem::Version.new(Rails.version) >= Gem::Version.new("5.0.0")
{ params: params }
else
params
end
end
end


spec/rails_helper.rb

Dir["#{__dir__}/support/**/*.rb"].each { |f| require f }

RSpec.configure do |config|
config.include ParamsWrapper
end


controller specでは下記のように呼び出します。


spec/controllers/users_spec.rb

get :show, params_wrapper(id: 1)


これでRails 4系以前では get :show, { id: 1 } が、Rails 5系以降では get :show, params: { id: 1 } が実行されます。

params_wrapper を挟むことでcontroller specの各所でRailsのバージョン分岐を書く必要がなくなってspecがシンプルになります。


実際にこの対応を行ったcommit

https://github.com/mitaku/komachi_heartbeat/pull/18/commits/e5c46a831d7332b262b72d052b97e6140fe2f442

量が多いと書き換えは大変ですが、元のspecとそんなに差分もなく違和感なく読める(と思う)のがいいです。


備考: sessionについて

今回は params だけだったのでこのような対応でしたが、 session も考慮すると対応が若干面倒くさそうな予感がしています。(今回のcontroller specだと session を使っていなかったので特に考慮していなかった)





  1. このサンプルではParamsWrapperをincludeしていますが、rails_helper.rbにメソッドを直接定義するのでもいいです