Gemfileの有無で変わる読み込まれる.rubocop.yml、そして優先順位について
最初に
予期せぬ~/.rubocop.yml
が読み込まれいてトラブっているのを見たので、
.rubocop.yml
がどういう順序で読み込まれたりするのかについて調査した。
説明するのが難しいけれど、書いて公開しておかないとせっかく調査したのに忘れてしまいそうなので、書いてみる。
複数の.rubocop.yml設定ファイルを読み込むRuboCop
ここで前提として、rubocopコマンドのコマンド引数で、親ディレクトリなどの祖先は指定しない。
これは、簡単のためというのもあるが、そもそもRuboCop自体想定されてないと考えられるためだ。
rubocop ..
みたいな形で親を指定して実行するとエラーが起きたので、そう考えられる。
ルールによっては、優先順位などが変わることもあるようだけど、基本的には以下のような感じ。
- Rubyファイルから見ると、同じ位置か上位にある
.rubocop.yml
のルール適用される。 - 複数の
.rubocop.yml
が見られる場合に、同じCopルールがあれば下にある.rubocop.yml
の方が優先順位が高い。
プロジェクトルートディレクトリというのは、Gemfileかgems.rbという名前のファイルがあるディレクトリ。
(GemfileはBundlerでよく使うけど、gems.rbは知らない)
コマンド実行位置が、ホームディレクトリでもプロジェクトルートディレクトリでもない場合は、
コマンド実行位置の.rubocop.ymlに加えて、
上位にあるプロジェクトルートディレクトリかホームディレクトリの.rubocop.ymlもあれば見られる。
ホームディレクトリのrubocop.ymlでrubocop-railsを読み込むべきではない。
gem install rubocop-rails
で、RuboCop本家で開発されているRails用のgemをインストールできる。
これで、(書くべきではないが実験のため)ホームディレクトリの.rubocop.yml
で、 rubocop-rails
を適用させる。
AllCops: NewCops: enable require: - rubocop-rails
RailsアプリにはアプリのルートディレクトリにGemfileがあるはずで、
Railsアプリのプロジェクトルートでない位置でrubocopコマンドを打つと、
コマンド実行位置の.rubocop.yml
に加えて、
RailsアプリのGemfileのあるプロジェクトルートにある.rubocop.yml
が読み込まれる。
しかし、Gemfileのない普通のRubyコードに対してrubocopコマンドを打つと、
コマンド実行位置の.rubocop.yml
に加えて、
ホームディレクトリの.rubocop.yml
も読み込まれる。
だから、もしホームディレクトリの.rubocop.yml
にRails用のルールがあれば、
RailsのコードじゃないのにRailsのルールを適用してきてしまうことになる。
だから、「ホームディレクトリに便利かも」みたいに思ってRails用のルールを適用させてしまうのはよくない。というより、誤っている。
Gemfileの有無で変わる.rubocop.ymlとは
上記の話を整理する。
ホームディレクトリに.rubocop.yml
があり、あるディレクトリにGemfile
と.rubocop.yml
があるとする。
このとき、あるディレクトリでコマンドを実行すると、Gemfile
のあるディレクトリの.rubocop.yml
のみが見られる。
ここで、もしGemfile
を削除すると、ホームディレクトリの.rubocop.yml
も見られる。
考え方的には、Gemfile
があるディレクトリなら何かのRubyアプリを作っているディレクトリで、そこに.rubocop.yml
があるなら、
ホームディレクトリにある個人用の.rubocop.yml
は適用されるべきではない、という考え方をとっているのだと思う。
ドキュメントも読んで確かめてみる
As an example, if RuboCop is invoked from inside /path/to/project/lib/utils, then RuboCop will use the config as specified inside the first of the following files: - /path/to/project/lib/utils/.rubocop.yml - /path/to/project/lib/.rubocop.yml - /path/to/project/.rubocop.yml - /.rubocop.yml - ~/.rubocop.yml - ~/.config/rubocop/config.yml - RuboCop’s default configuration
公式ドキュメントに書いてある英語の細かいニュアンスなどがわかりにくいが、優先順位が書いてある。
よく見ると、ホームディレクトリよりルートディレクトリの方が優先順位が高かったりして、必ずしも子の方が優先されるというわけでもないらしい。
ただ、普通はPCのルートディレクトリに.rubocop.yml
を書いたりしないだろうし、気にすることではないだろう。
しかし、公式ドキュメントのどのあたりを読めば、コマンド実行位置の.rubocop.yml
だけでなく、ホームディレクトリかGemfileのあるプロジェクトルートディレクトリのどちらかの.rubocop.yml
が読み込まれるという話が書いてあるのかわからなかった。
最後に
読み込まれる.rubocop.yml
が1つだけなのか複数あるのかとか、どういう順番なのかとか、そういうのを一切知らずになんとなく使ってきていたので、読み込まれる順番がわかってよかった。