RuboCopを導入してみる


# TL;DR
この記事はこの記事は[RUNTEQ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/runteq) 6日目の記事です。
今回はRubyのコード解析ツールRuboCopを導入しようとする時の設定について紹介します。
# 対象読者
RuboCopを導入してみようと考える初心者
## はじめに
RuboCopはディレクトリ直下に設定ファイル(.rubocop.yml)をおくことで使用できます。
.rubocop.ymlをおいたらGemfileに,

```Gemfile
group 'development' do
  ...
  gem 'rubocop', require: false
end
```
と記載して， bundle installを行えばもう完了です。

RuboCopでは.rubocop.ymlの設定に応じて，　
以下の5つに関して指摘が行われます。
こうしたコードのチェックルールのことを「cop」と呼んでいきます。

- LayOut (レイアウトに関するCop)
- Lint (誤りである可能性が高い部分やbad practiceを指摘するCop)
- Metrics (クラスの行数や文字数などに関してのCop)
- Naming (命名規則に関するCop)
- Style (スタイルについてのCop)

*** Rails CopsとPerformance Copsは最新のRuboCopから外されているので，外部の記述を参考にするときは注意してください。
RuboCop 本体から Rails Cops が外される　
(http://koic.hatenablog.com/entry/extract-rails-cops-from-rubocop-core)
RuboCop 本体から Performance Cops が外される
(http://koic.hatenablog.com/entry/extract-performance-cops-from-rubocop-core)

この中ではLint copsがバグに繋がる可能性のあるので重要です。その他のCopはコードの見た目に関わる部分が中心なのでもし古いアプリであれば後回しでも良いかもしれません。 

## 導入したらまずコードを綺麗にする

途中からRuboCopを入れる場合は空行混じりであったりインデントの崩れがあったりコードの見た目が気づかないうちに崩れているケースがあります。 rubocop -a --only で一部の規則だけに絞ってRuboCopを自動で走らせることができます。(-a はautoの略です。 Cop supports --auto-correct. と記述されているcopでは自動修正できます。)

####メソッド定義やメソッド呼び出しの()をいい感じに
```bash

$ rubocop -a --only Style/DefWithParentheses,\
Style/MethodCallParentheses,\
Style/MethodDefParentheses
```
#### インデント崩れを修正
```bash

$ rubocop -a --only Style/IndentationConsistency,\
Style/IndentationWidth,\
Style/MultilineOperationIndentation
```
#### 空行をいい感じに
```bash

$ rubocop -a --only Style/EmptyLineBetweenDefs,\
Style/EmptyLines,\
Style/EmptyLinesAroundAccessModifier,\
Style/EmptyLinesAroundBlockBody,\
Style/EmptyLinesAroundClassBody,\
Style/EmptyLinesAroundMethodBody,\
Style/EmptyLinesAroundModuleBody,\
Style/TrailingBlankLines
```
#### コロンやカンマの前後のスペースをいい感じにする
```bash

$ rubocop -a --only Style/SpaceAfterColon,\
Style/SpaceAfterComma,\
Style/SpaceAfterNot,\
Style/SpaceAfterSemicolon,\
Style/SpaceAroundEqualsInParameterDefault,\
Style/SpaceBeforeSemicolon
```
#### 行末のスペース削除
```bash

$ rubocop -a --only Style/TrailingWhitespace
```

## いい感じにする設定
それでは設定についてみていきます。 
なお一から設定を考えるのは大変であるので， github上に公開されている
https://github.com/onk/onkcop/blob/master/config/rubocop.yml を使用しています。
https://github.com/onk/onkcop からgemとしても利用できるようですが， 
最新ではない部分もあるのでカスタマイズが必要です。
したがって自分の場合はgemではなくファイルだけ引っ張って一部変更しています。
基本的に上記のRuboCopの設定を利用して，自分で新たに設定する設定をファイルの上部に記述して上書きするイメージです。
上記との変更点を中心に紹介するので，全て見てみたい方は上記リンクを参考にしてください。

### はじめに

```.rubocop.yml
AllCops: 
  Exclude:
    - "node_modules/**/*" # rubocop config/default.yml
    - "vendor/**/*"       # rubocop config/default.yml
    - "db/schema.rb"
```
サービスに合わせて自動生成されるファイル等を除外します。

### テンプレートから外れる設定

サービスに固有の設定を書きます. 不具合が出たけど変更したくない場合に随時falseにして，
ファイルの上部に設定を置いていくイメージです。

```.rubocop.yml
# modelのscopeで -> (params) {
# といった()で引数を囲む書き方をすでにしちゃってたらfalseにする
Layout/SpaceInLambdaLiteral:
  Enabled: false

# privateメソッドのselfの書き方の指定
Lint/IneffectiveAccessModifier:
  Enabled: false

# メソッドの接頭辞にget_とかset_とかつけないルール
# すでにつけっちゃってて面倒とかだとfalseにする
Naming/AccessorMethodName:
  Enabled: false

# gemの並びを名前順にするもの
# すでにバラバラで修正面倒だと変にいじるとこわいのでfalseにする
Bundler/OrderedGems:
  Enabled: false
```

#### LayOut
LayOutに関する設定です。下は最新のrubocopでは書き方が変わっていたので記述を変更しました。

```.rubocop.yml

# special_inside_parentheses (default) と比べて
# * 横に長くなりづらい
# * メソッド名の長さが変わったときに diff が少ない
Layout/IndentFirstArrayElement:
  EnforcedStyle: consistent

# ({ と hash を開始した場合に ( の位置にインデントさせる
# そもそも {} が必要ない可能性が高いが Style/BracesAroundHashParameters はチェックしないことにしたので
Layout/IndentFirstHashElement:
  EnforcedStyle: consistent
private/protected は一段深くインデントする

Layout/IndentationConsistency:
　EnforcedStyle: indented_internal_methods

```

#### Naming

Namingに関する設定です。
こちらの設定は新たに無効化しました。

```.rubocop.yml
# has_ から始まるメソッドは許可する
#　色々使うことありそうなので無効化
Naming/PredicateName:
  # NamePrefixBlacklist:
  #   - "is_"
  #   - "have_"
  # NamePrefix:
  #   - "is_"
  #   - "have_"
  Enabled: false
```

#### Style

Styleに関する設定です。
違和感があったものを無効化しました。

```.rubocop.yml
### この辺は違和感があったので無効化しました

# 複数行の場合はケツカンマを入れる(Arrayリテラル)
Style/TrailingCommaInArrayLiteral:
  Enabled: false
  # EnforcedStyleForMultiline: comma

# 複数行の場合はケツカンマを入れる(Hashリテラル)
# => 気持ち悪いので無効化
Style/TrailingCommaInHashLiteral:
  # EnforcedStyleForMultiline: comma
  Enabled: false

# この辺はダブルクォートを強制する必要がないと思ったのでコメントアウト
# * 式展開したい場合に書き換えるのが面倒
# * 文章ではダブルクォートよりもシングルクォートの方が頻出する
# ことから EnforcedStyle: double_quotes 推奨
# Style/StringLiterals:
#   EnforcedStyle: double_quotes

# 式展開中でもダブルクォートを使う
# 普段の文字列リテラルがダブルクォートなので使い分けるのが面倒
# Style/StringLiteralsInInterpolation:
#   EnforcedStyle: double_quotes
```

一旦以上です。
# 参考

#### 参考にしたRuboCop
https://github.com/onk/onkcop/blob/master/config/rubocop.yml
#### 公式系
- https://github.com/rubocop-hq/rubocop
- https://rubocop.readthedocs.io/en/latest/configuration

#### 警告の一覧とか
- https://qiita.com/tanish-kr/items/abb881c098b3df3f9871

# あとがき

RuboCopは，最初その存在すら知らないままコードを書いていましたが, もっと学習の初期段階から知っておいて使えていればよかったなーと思うツールです。

書き方が色々あるRubyにおいて， RuboCopの指摘修正を通じて自然と文法が覚えられますし， コピペが増えがちな初学者でも統一感のあるコードを書くことができます。
また複数人での開発やPRを見てもらう際においても自動でRuboCopを走らせるよう設定しておくことで， コーディング規約が簡単に適用でき， 効率化を図ることができます。

エラーが沢山出てしまって大変なイメージがありますが， falseの設定を多めにしてゆるい規約からでもぜひ始めてみましょう。

また次はRuboCopでよく指摘されるエラーについてまとめたいと思います。