何度もレビューで指摘することはRuboCopのルールとして追加して、自動化しておくと便利です。
この記事では、RuboCopで新しいルールを作る方法を紹介します。
参考にしたページ
これがとても参考になった。
github.com
Copの書き方は独特なので、RuboCopリポジトリの lib/rubocop/cop
ディレクトリにある他Copをいくつか読むと参考になります。
github.com
Custom Cop の作り方
ここでは例としてMatzの名前を "Hiroyuki Matsumoto" と間違って書いたとき、検知できるCopを作ってみます。
まずは .rubocop.yml
に require
の行を追加します。
require: './lib/custom_cops/matz_name'
AllCops:
次に、 lib/custom_cops/matz_name.rb
に新しいルールを書きます。
module CustomCops
class MatzName < RuboCop::Cop::Cop
BAD_NAME = "Hiroyuki Matsumoto"
GOOD_NAME = "Yukihiro Matsumoto"
MSG = "Use '#{GOOD_NAME}' instead of '#{BAD_NAME}'."
def on_str(node)
add_offense(node) if node.source.include?(BAD_NAME)
end
def autocorrect(node)
->(corrector) {
new_code = node.source.gsub(BAD_NAME, GOOD_NAME)
corrector.replace(node.source_range, new_code)
}
end
end
end
いくつか独特なルールがあるので、簡単に説明します。
on_xxx
メソッドはRubyのコード内で該当するコードが見つかった時に呼ばれるメソッドです。
たくさんあるので興味ある人はRuboCopリポジトリのlib/rubocop/ast/traversal.rb
を読むと良いです。
基本的には「それっぽいメソッドを定義して、テスト書いてみて試す」とか「他Copの実装をパクる」で頑張ります。
add_offense
はルール違反を検知した時に呼び出します。
引数に渡している node
に対して、MSG
定数の文字列をメッセージとして表示します。
メッセージを動的に変えたい場合は message
オプションで変える事もできます。
add_offense(node, message: "foo")
autocorrect
メソッドは実装すると --auto-correct
に対応することができます。
コード例のように proc を返すようにする必要があります。
テストの書き方
spec/rails_helper.rb
で下記のようにCustom Copを読み込むコード、RSpecのヘルパーメソッドの読み込みを行います。
require "rubocop"
Dir[Rails.root.join("lib/custom_cops/**/*.rb")].each { |f| require f }
require "rubocop/rspec/support"
RSpec.configure do |config|
config.include(RuboCop::RSpec::ExpectOffense)
end
RuboCopリポジトリのテストコードを参考にしながら、コードを書きます。
require "rails_helper"
RSpec.describe CustomCops::MatzName do
subject(:cop) { described_class.new }
it "registers an offense" do
expect_offense(<<-RUBY.strip_indent)
MATZ_NAME = "Hiroyuki Matsumoto"
^^^^^^^^^^^^^^^^^^^^ Use 'Yukihiro Matsumoto' instead of 'Hiroyuki Matsumoto'.
RUBY
end
it "autocorrects" do
new_source = autocorrect_source('MATZ_NAME = "Hiroyuki Matsumoto"')
expect(new_source).to eq 'MATZ_NAME = "Yukihiro Matsumoto"'
end
end
できればRuboCopにプルリクを投げよう
もし有用なCopを実装できたら、RuboCopにプルリクを投げると良いです。
- RuboCopのメンバーがコードレビューしてくれる
- 世界中のRuboCopユーザーがIssue挙げたり、メンテしてくれる
などのメリットがあります。
普段からRuboCopを便利に使わせて頂いているので、たまには恩返しとしてプルリクを送りたいですね。
おわり
「人間が何度もレビューで指摘する」は真面目で良いことだとは思いますが、怠惰力が足りないです。
機械的にレビューできる箇所は機械に任せ、我々は人間にしかできない「自動化の難しいところのレビュー」や「ビールを飲みながらアニメを観る」などを頑張りたい。