rubocopを使ったことがなかったのですが、ここへきて使ってみることにしました。 Railsを使って開発中の幾つかのWebアプリやAPIに対して試験的に導入してみて、rubocopでチェックして、指摘を確認し、修正し、またチェックして・・・っていう一連の流れがつかめたように感じたので、自分なりのプラクティスを纏めておきます。
rubocopは、rubyのコードに対して、コーディング規約に準拠していることをチェックする、いわゆる静的コード解析ツール。
bbatsov/rubocopでオープンソースとして公開されていて、ライセンスは、独自ライセンスっぽい。
チェックする内容は、rubocop作者によるrubyのコードスタイル標準に則っているか、で、その標準は、bbatsov/ruby-style-guide で公開されており、様々な言語に翻訳されている。日本語版は、https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md にある。
開発中のRailsアプリに、何も考えずにrubocopを入れてチェックすると、大量の規約違反が検出されて途方に暮れる(僕はなった)。 そのあと、闇雲に直し始めて、場合によっては、
などの弊害が生まれてしまうので、それは避けたい。
そうならないために、事前にrubocopを使っていく際のフローを確立して、意識しておく必要があると思った。
そこで、
という単純なフローを定義して、このフローに乗っかってみることにした。
ここでは、開発中のRailsアプリにrubocopを導入することを前提としている。
環境は、
Gemfileに、
group :development do
gem 'rubocop', require: false
end
を追記して、bundle install
する。
まず、アプリケーションルートディレクトリに、.rubocop.yml
を作成し、
Rails:
Enabled: true
を記述する。 これによって、標準の規約+Rails固有の規約が有効になる。
続いて、bundle exec rubocop --auto-gen-config
を実行し、.rubocop_todo.yml
が生成されることを確認する。
この.rubocop_todo.yml
は、現状の規約違反が全て記録される。
さらに、.rubocop.yml
の先頭に
inherit_from: .rubocop_todo.yml
を追記する。
そうすると、違反はあるけど一旦無視する、という状態ができ、この状態をスタートラインとする。
.robocop_todo.yml
の中の特定のルールについて、コメントアウトし、bundle exec rubocop
を実行する。
すると、コメントアウトしたルールに対する違反が出力される。
rubocopの違反の出力に含まれるメッセージを確認し、何が指摘されているのかを把握する。
よくわからない場合は、RuboCop: The Ruby Linter that Serves and Protectsの「Cops Documentation」を見ると、ルールの内容がわかる。「bad」、「good」のように例が書かれているものもあるのでわかりやすい。
指摘された違反を「正しい」と見做したい場合がある。 例えば、日本語のコメントを正しいと解釈したり、1行あたりのカラム数を100にしたい(デフォルトは80)、など。
こういった場合は、.rubocop_todo.yml
でコメントアウトした内容を、.rubocop.yml
に書くことで、
検証のルールをカスタマイズすることができる。
例えば、日本語のコメントを認めるには、
Style/AsciiComment:
Enabled: false
を.rubocop.yml
に追記する、など。
指摘された違反が確かに違反であると言える場合は、素直にコードを直す。 この時、修正が単純なもので済むこともあるし、場合によっては、リファクタリングが必要になるケースもあると思う。 なので、修正内容をよくよく検討する必要がある。
の違反は、一旦.rubocop_todo.yml
をそっと元に戻して、修正を後回しにした方が効率がいい。
再度、同じ条件で(.rubocop.yml、.rubocop_todo.ymlを書き換えずに)bundle exec rubocop
を実行し、違反がなくなっていることを確認する。
そして、テストがあるならここでテストする。テストがないなら追加する。
テストにパスして、同じルールに対する違反の修正が全て解消できたなら、この時点でコミットしてしまうのがいい気がした。
あとは、.rubocop_todo.yml
の中身に対して、1つずつ上記の作業を繰り返していき、
.rubocop_todo.yml
が空っぽになるまで続ける。
以上が、僕なりのフローです。 今後、しばらくこのフローに乗っかってrubocopライフを生きていきたい。