RuboCopの導入、使用手順のメモ

## はじめに
以下の内容をまとめています。

- RuboCopの導入〜実行
- 修正の手順
- コミット時にでRuboCopを回すための設定（pre-commitを使用）

## 導入

Gemfile に記述 → bundle installで完了です。
尚、今回の記事ではしていませんが、公式からはバージョン指定することを勧めています。
（RuboCop のバージョンアップで予期しない変化が起きないように）
参考：[RuboCop](https://github.com/rubocop-hq/rubocop#installation)

```
# Gemfile
group :development do
  ...省略
  gem 'rubocop', require: false
  gem 'rubocop-rails', require: false
end
```
```
% bundle install
```

rubocop-rails は、Rails の構文についてチェックしてくれるものです（rubocop は Ruby)
参考：[RuboCop Rails](https://github.com/rubocop-hq/rubocop-rails)

また、`require: false` を付ける理由について、下記の記事が参考になりました。
参考：[rubocopをbundlerでインストールするときにrequire: falseにする理由](https://qiita.com/S42100254h/items/170e88d888330ca92701)

## 使用手順（検査〜修正）
実際に使ってみましょう。

```
% rubocop
```
このコマンドで全ファイルのチェックが始まります。
開発途中で RuboCop を導入した場合は、この段階でたくさん怒られてしまうと思います。(私がそうでした…)

### 違反内容を出力する

現状の違反内容を出力するため、下記のコマンドを実行します。

```
% bundle exec rubocop --auto-gen-config
```
すると、 `.rubocop.yml` と `.rubocop_todo.yml` というファイルが生成されます。
`.rubocop_todo.yml` の中をみると、違反内容が項目ごとに記載されています。現状の違反をこのファイルに退避させているイメージです。
（ここでもう一度 rubocop コマンドを実行すると、何も怒られなくなります。）

```.rubocop_todo.yml

# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2020-12-09 22:58:27 UTC using RuboCop version 1.3.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 1
# Cop supports --auto-correct.
Layout/EmptyLines:
  Exclude:
    - 'spec/models/profile_spec.rb'

# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
Layout/EmptyLinesAroundModuleBody:
  Exclude:
    - 'spec/support/login_support.rb'

# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: Width, IgnoredPatterns.
# …省略
```
簡単にですが、冒頭の分を訳してみます
> This configuration was generated by rubocop --auto-gen-config on 2020-12-08 02:09:32 UTC using RuboCop version 1.3.1. The point is for the user to remove these configuration records one by one as the offenses are removed from the code base. Note that changes in the inspected code, or installation of new versions of RuboCop, may require this file to be generated again.

> このファイルはRuboCopバージョン1.3.1上でrubocop --auto-gen-config(コマンド)によって作られました。ポイントは、アプリのソースコードの違反を一つずつ確認しながら、ここで出力されたレコードを取り除けるようになっているということです。検査したアプリのソースに変更があったり、RuboCopのバージョンアップをした場合には、もう一度このファイルを作成した方がよいかもしれません。

つまり、`.rubocop_todo.yml`の違反内容を一つずつ確認しながら、アプリのコードを修正していくという作業が必要になります。

### 違反箇所を修正する
１つ目のコメントアウトを外して、rubocopコマンドを実行してみましょう。

```.rubocop_todo.yml
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2020-12-09 22:58:27 UTC using RuboCop version 1.3.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 1
# Cop supports --auto-correct.
#Layout/EmptyLines:                       # コメントアウト
#  Exclude:                               # コメントアウト
#    - 'spec/models/profile_spec.rb'      # コメントアウト

# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
Layout/EmptyLinesAroundModuleBody:
  Exclude:
    - 'spec/support/login_support.rb'

# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: Width, IgnoredPatterns.
# …省略

```

```
% rubocop

# 結果
Offenses:

spec/models/profile_spec.rb:36:1: C: Layout/EmptyLines: Extra blank line detected.

123 files inspected, 1 offense detected, 1 offense auto-correctable
```

内容は、Layout/EmptyLines ということで、「余分なブランクの行があったぞ」ということでした。
（もちろん、これは私の例ですので、人によって結果は異なります）
具体的には、以下の部分でした。

```profile_spec.rb
  end
  # ブランクの行が２つある
  # ブランクの行が２つある
  describe "profileの検索" do
```
```profile_spec.rb
  end
  # 一行削除
  describe "profileの検索" do
```
こんな流れで、ソースを修正していきます。

シェルの出力を見ても、違反の内容がわからないときは、下記のページで検索すると分かりやすいです。
「何がいけなくて、どうするべきか」をbefore / after形式で教えてくれます。
参考：[RuboCop Docs](https://docs.rubocop.org/rubocop/1.2/index.html)

### 自動修正する
下記のコマンドで検査しながら、自動で修正できる場合もあります。

```
% rubocop -a
```

### 違反を許可する
ただし、そこまでやらなくても…。という違反もあると思います。

検知範囲から逃したい場合は、`.rubocop.yml` に対象から外す旨の記述をしていきます。
`.rubocop.yml` が設定ファイルになっている訳ですね。

例えば、今回の Layout/EmptyLines を許可したい場合は次のように書きます。

```.rubocop.yml
# 余分な空白行を許可する
Layout/EmptyLines:
  Enabled: false
```
この状態で rubocop を実行すると、出ていたエラーが無くなります。

```
% rubocop

# 結果
...........................................................................................................................

123 files inspected, no offenses detected
```

また、ファイルごと検査対象から外すこともできます。

```.rubocop.yml
AllCops:
  TargetRubyVersion: 2.6
  TargetRailsVersion: 6.0
  Exclude:
    - 'bin/**/*'
    - 'db/**/*'
```

このあたりは、いろんなやり方を参考にしながら作っていきました。個人やチームの方針でオリジナルの`.rubocop.yml`が出来上がっていくと思います。
https://qiita.com/kaito_program/items/c7d21f2e90cf9b7f7cf2
https://qiita.com/arthurbryant/items/73908b54b44dcaece864

## コミット時に自動で検査する

RuboCopを導入しても、使わなければまた違反コードが溜まっていってしまって意味がありません。コードスタイルを確立するという意味でも、逐一確認していきたいです。
そこで、 `pre-commit` というgemを導入し、コミット時に rubocop が実行されるようにします。

下記を参考に導入していきます
参考：[pre-commit](https://github.com/jish/pre-commit)

```
# Gemfile
group :development do
  ...省略
  rubocop, require: false
  rubocop-rails, require: false
  gem 'pre-commit', require: false  # 追加
end
```
```
% bundle install
% bundle exec pre-commit install
% git config pre-commit.ruby "bundle exec ruby"
```
初めて導入した際、なかなか `pre-commit` が動作しませんでしたが、２行目の `bundle exec pre-commit install` をすると、出来るようになりました。
参考：[[Ruby] rubocopをコミット時に自動で走らせる & 出来る限り自動で修正する](https://qiita.com/kazuooooo/items/d8dd165623a9bd6a5a69)

今の設定を確認してみましょう

```
% pre-commit list
Available providers: default(0) git(10) git_old(11) yaml(20) env(30)
Available checks   : before_all ci coffeelint common console_log csslint debugger gemfile_path go go_build go_fmt jshint jslint json local merge_conflict migration nb_space pry rails rspec_focus rubocop ruby ruby_symbol_hashrockets scss_lint tabs whitespace yaml
Default   checks   : common rails
Enabled   checks   : common rails
Evaluated checks   : tabs nb_space whitespace merge_conflict debugger pry local jshint console_log migration
Default   warnings : 
Enabled   warnings : 
Evaluated warnings :
```
以下のコマンドで、 rubocop を有効にします


```
% git config pre-commit.checks "[rubocop]"

% pre-commit list
Available providers: default(0) git(10) git_old(11) yaml(20) env(30)
Available checks   : before_all ci coffeelint common console_log csslint debugger gemfile_path go go_build go_fmt jshint jslint json local merge_conflict migration nb_space pry rails rspec_focus rubocop ruby ruby_symbol_hashrockets scss_lint tabs whitespace yaml
Default   checks   : rubocop  # 変化点
Enabled   checks   : rubocop  # 変化点
Evaluated checks   : rubocop  # 変化点
Default   warnings : 
Enabled   warnings : 
Evaluated warnings :
```

ちゃんと動くか、違反している状態でコミットしてみます。

```
% git commit -m "test"
pre-commit: Stopping commit because of errors.
Inspecting 1 file
C

Offenses:
以下違反内容...

pre-commit: You can bypass this check using `git commit -n`
```
`pre-commit: Stopping commit because of errors.` と出て無事にコミットが中断されました！


## おわりに
初めて導入したときは、修正対応が大変でしたが、知らなかった書き方を知れたりして得るものが多かったです。
学習初期段階から積極的に使っていくべきツールだと思いました。

### 参考記事
[RuboCop](https://github.com/rubocop-hq/rubocop#installation)
[RuboCop Rails](https://github.com/rubocop-hq/rubocop-rails)
[rubocopをbundlerでインストールするときにrequire: falseにする理由](https://qiita.com/S42100254h/items/170e88d888330ca92701)
[RuboCop Docs](https://docs.rubocop.org/rubocop/1.2/index.html)
[[Ruby] rubocopをコミット時に自動で走らせる & 出来る限り自動で修正する](https://qiita.com/kazuooooo/items/d8dd165623a9bd6a5a69)
[【Rails】RuboCopの基本的な使用方法と出力の見方](https://qiita.com/terufumi1122/items/ad55bf8713c0df053f58)