@vividmuimui
2019/04/03
社内LT
便利copとかの話ではないです。
継承(inherit)に関する3点の話です。
RuboCop では、共通設定ファイルを利用する方法がいくつかある。
inhert_from
.rubocop_todo.yml
が代表的inherit_gem
onkcop
, meowcop
が代表的inherit_from: .rubocop_todo.yml
inherit_gem:
onkcop:
- "config/rubocop.yml"
- "config/rails.yml"
inherit_from
にはURLもかける!inherit_from:
- http://www.example.com/rubocop.yml
会社共通の設定とかはGitHubにあげて
https://raw.githubusercontent.com/xxx
を参照するのが手っ取り早そう?
Rubyのバージョンが最新に追従できてない、とかもあると思うので、現実的にはGemで提供するのが正しそう。
子ファイル(例: .rubocop.yml
)で親ファイル(例:
.rubocop_todo.yml
)の設定を継承するときに、
子ファイルで親ファイルの設定を上書きできる
# .rubocop_todo.yml
Style/CollectionMethods:
PreferredMethods:
collect: map
# .rubocop.yml
inherit_from: '.rubocop_todo.yml'
Style/CollectionMethods:
PreferredMethods:
collect: collect # こっちの設定が有効
RuboCopの設定は、Hash
とArray
で設定される。
Style/CollectionMethods:
# hashの例
PreferredMethods:
collect: map
# arrayの例
Exclude:
- 'foo/bar.rb'
継承したときに、
ArrayがOverrideなのは、そうじゃないと親の設定を子で無効化できないから。MergeだとYamlで空Arrayを書いても、親の設定が残ってしまう。
Hashの場合は~
(Yamlのnull)で、親の設定をキャンセルできる。
inherit_modeでArrayの継承時の挙動を変更できる。
OverrideからMergeに変更できる
inherit_from:
- 'shared.yml'
inherit_mode:
merge:
- Exclude
Style/For:
inherit_mode:
override:
- Exclude
inherit_from
Include/Exclude
inherit_from: .rubocop_todo.yml
Style/CollectionMethods:
Exclude:
- 'foo/bar.rb'
どちらも、パスは絶対パス・相対パスどちらも書ける。
相対パスはどこからの相対なのか?
inherit_from
に書く相対パスは、inherit_from
が書いてあるファイルからの相対パス
# .rubocop.yml
inherit_from: '../.rubocop_todo.yml'
こう書いた場合、
.rubocop.yml
からみて../
にある.rubocop_todo.yml
を読み込む。
Include/Exclude
の相対パスStyle/CollectionMethods:
Exclude:
- 'foo/bar.rb'
Include/Exclude
の設定が書かれているファイル名によって変わる!
Include/Exclude
の相対パス.rubocop
で始まる設定ファイルの場合
.rubocop.yml
や
.rubocop_todo.yml
など
rubocop
コマンドを実行したディレクトリからの相対パス
.my_rubocop_config.yml
や
rubocop.yml
(ドットなし)など
.
├── config
│ ├── .my_rubocop_config.yml
│ ├── .rubocop_todo.yml
│ └── .rubocop.yml
└── src
└── sample.rb
# .rubocop.yml
inherit_from:
- .my_rubocop_config.yml
- .rubocop_todo.yml
このような状況とします。
rubocopコマンドは、ルートディレクトリで以下のように実行するとします
$ rubocop -c config/.rubocop.yml
.
├── config
│ ├── .my_rubocop_config.yml
│ ├── .rubocop_todo.yml
│ └── .rubocop.yml
└── src
└── sample.rb
# config/.rubocop.yml
# config/.rubocop_todo.yml
Style/CollectionMethods:
Exclude:
# .rubocopで始まるので、設定ファイルからの相対
- '../src/sample.rb'
# config/.my_rubocop_config.yml
Style/CollectionMethods:
Exclude:
# .rubocopではないので、実行ディレクトリからの相対
- 'src/sample.rb'
.rubocop.yml
がリポジトリルートに置いてあるケースでは、ほぼ問題にならない。
ただ、tools/rubocop/
などに設定ファイル(.rubocop.yml
など)をおいてるときには注意しなければいけない。
例えば、以下のようなケースの場合、.rubocop
で始めないファイル名のほうが楽。
.
├── src
│ └── server
│ └── test
│ └── foo.rb
└── tool
└── rubocop
└── config
└── rubocopの設定ファイル
rubocopの設定ファイルがルートになく、
src
ディレクトリでrubocopを動かすようなケース
実行コマンドが次のようになるケース
$ rubocop -c ../tool/rubocop/config/{rubocopの設定ファイル}
コマンドの実行ディレクトリが設定ファイルと同じ場所の場合は話が別です。
(tools/rubocop/config
でrubocopコマンドを動かすようなケース。そういうケースはあまりなさそうだが。。)
.rubocop
で始めないファイル名のほうが楽な理由
例えば、test
ディレクトリはまるっと無視したいCopがあったとき、
# rubocopの設定ファイル
Foo/BarCop:
Exclude:
- '**/test/**/*.rb'
というように書きたくなるが、
.rubocop
で始まるファイルの場合
**/
が効かない。
.rubocop
で始まらないファイルの場合
rubocop
コマンドの実行ディレクトリからの相対パスなので、上記の設定で問題ない。
inherit_from
にはURLが書けるinherit_mode
inherit_mode
でArrayの上書き設定をMergeに変更できる
inherit_from
に書くパスは、inherit_from
が書かれた設定ファイルからの相対
Include/Exclude
に書くパスは
.rubocop
で始まる場合は、設定ファイルからの相対
tools/
などに置くときは、.rubocop
で始まらないファイル名のほうが楽