15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RuboCop とスタイルガイドを組み合わせて活用する

Posted at

RuboCop は、Ruby の為のスタイルチェッカであり、bbatsov/ruby-style-guide をベースにルールが作られています。
この記事では RuboCop と Ruby Style Guide を組み合わせて有効活用する方法について紹介します。

TL;DR

  • RuboCop のメッセージだけでは足りていない情報が、Ruby Style Guide で補完できる。
  • .rubocop.ymlに以下を追記するだけで、Ruby Style Guide と RuboCop を連携できる。
AllCops:
  DisplayStyleGuide: true
  # 日本語を使いたい場合は以下の一行も追加
  StyleGuideBaseURL: https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md

RuboCop のメッセージが不親切

何故 RuboCop をスタイルガイドと組み合わせて使用することが必要なのでしょうか?
その理由のひとつに、RuboCop のデフォルトのメッセージが不親切、ということが上げられます。

以下のコードを例に考えてみましょう。

test.rb
for x in [a, b, c] do
  something(x)
end

このコードに対して RuboCop を実行すると、以下のように「for文の代わりにeachを使用するべき」という警告が出ます。

$ rubocop
Inspecting 1 file
C

Offenses:

test.rb:1:1: C: Prefer each over for.
for x in [a, b, c] do
^^^

1 file inspected, 1 offense detected

このメッセージからは「eachを使用すべき」ということはわかりますが、それ以上の情報は含まれていません。
つまり、「なぜforよりeachを使用すべきなのか」「foreachの違いは何なのか」と言った情報は、これだけでは得ることが出来ません。
そのため、このメッセージを見た人は自分でforの意味を調べるか、ただ盲目的に RuboCop の指摘に従うしかありません(そしてこれは最悪です)。

このような不親切なメッセージは、このforに関するルール以外でも多く見られます。
では、どうしたら RuboCop のメッセージからより詳細な情報を得ることができるでしょうか?

Ruby Style Guide を参照する

冒頭にも述べたとおり、RuboCop は Ruby Style Guide のスタイルをベースに作られています。
そのため(特に Style 系のルールに関しては) Ruby Style Guide にそのスタイルに関する詳細な記述が存在することが多いです。

例えば、先程の例であるforに関するルールに関しても、その詳細な記述がスタイルガイドに存在します。


  • Do not use for, unless you know exactly why. Most of the time iterators
    should be used instead. for is implemented in terms of each (so you're
    adding a level of indirection), but with a twist—for doesn't
    introduce a new scope (unlike each) and variables defined in its block
    will be visible outside it.
    [link]

    arr = [1, 2, 3]
    
    # bad
    for elem in arr do
      puts elem
    end
    
    # note that elem is accessible outside of the for loop
    elem # => 3
    
    # good
    arr.each { |elem| puts elem }
    
    # elem is not accessible outside each's block
    elem # => NameError: undefined local variable or method `elem'
    

https://github.com/bbatsov/ruby-style-guide#no-for-loops

これを参照することで、RuboCop のメッセージだけでは得られなかった「何故eachを使用すべきなのか」を知ることが出来ます。

ですが、RuboCop に指摘を受ける度にスタイルガイドを探すのは大変です。
もっといい方法はないのでしょうか?

RuboCop にスタイルガイドの URL を出力させる

解決策として、RuboCop にスタイルガイドの URL を出力されることが出来ます。

先程のコードに対して、もう一度 RuboCop を走らせてみましょう。今度は--display-style-guideオプション付きで RuboCop を実行してみます。

Inspecting 1 file
C

Offenses:

test.rb:1:1: C: Prefer each over for. (https://github.com/bbatsov/ruby-style-guide#no-for-loops)
for x in [a, b, c] do
^^^

1 file inspected, 1 offense detected

先程と違い URL が出力されていることがわかると思います。
この URL は指摘に対応するスタイルガイドの項目へのリンクです。

このように--display-style-guideオプションを付与して RuboCop を実行すると、指摘に対してのより詳細な情報を手軽に知ることが出来るようになります。

また、毎回このオプションを指定するのは大変です。
.rubocop.ymlに以下の記述を追加することで、オプションの指定を省略することが出来ます。

AllCops:
  DisplayStyleGuide: true

日本語でスタイルガイドを読む

ところで、先程上げたスタイルガイドは英語で書かれています。
英語に自信のない方など、日本語で書かれたスタイルガイドを読めたほうが嬉しいという方も多いのではないでしょうか?

このスタイルガイドは多言語に翻訳されていて、勿論日本語にも翻訳がなされています。
日本語のスタイルガイドはこちらから読むことが可能です。 https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md

例えば、先程のforの例は以下のように翻訳されています。


  • forは、どうしても使わなければいけない明確な理由が明言できる人以外は、使ってはいけません。
    多くの場合は代わりにイテレータを使うべきです。
    foreachをつかって実装されています(だから、より遠回しです)が、
    forは(eachと違い)新しいスコープを導入せず、
    そのブロック内で定義された変数は、ブロックの外からも見えます。
    [link]

    arr = [1, 2, 3]
    
    # 悪い例
    for elem in arr do
      puts elem
    end
    
    # elemはループの外からも参照できることに注意しましょう
    elem # => 3
    
    # 良い例
    arr.each { |elem| puts elem }
    
    # elemはeachブロックの外からは参照できません
    elem # => NameError: undefined local variable or method `elem'
    

https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md#no-for-loops

また、この翻訳されたスタイルガイドの URLの を RuboCop に出力させることも可能です。
先程の.rubocop.ymlに以下のように1行追記して下さい。

AllCops:
  DisplayStyleGuide: true
  StyleGuideBaseURL: https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md

この設定を適用した上で RuboCop を実行することで、以下のような出力が得られます。

Inspecting 1 file
C

Offenses:

test.rb:1:1: C: Prefer each over for. (https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md#no-for-loops)
for x in [a, b, c] do
^^^

1 file inspected, 1 offense detected

URL が日本語のものになっていますね。

まとめ

このように RuboCop を少し設定するだけで、RuboCop からの指摘をより有意義なものとすることが出来ます。
RuboCop からされた指摘をなんとなくで直していた方や、「言ってることは分かるけど理由くらい言ってよ…」と思っていた方は、是非この設定をお試しください。

15
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?