【Rails】RuboCop 導入編（2023年7月版）

# 環境

- ruby 3.2.2
- Rails 7.0.5
- [rubocop 1.54.1](https://github.com/rubocop-hq/rubocop) ※ 2023/7/5時点での最新版（以下も同様）
- [rubocop-rails 2.20.2](https://github.com/rubocop-hq/rubocop-rails)
- [rubocop-rspec 2.22.0](https://github.com/rubocop-hq/rubocop-rspec)
- [rubocop-performance 1.18.0](https://github.com/rubocop-hq/rubocop-performance)

# インストール

```ruby:Gemfile
group :development do
  gem 'rubocop', require: false
  gem 'rubocop-performance', require: false
  gem 'rubocop-rails', require: false
  gem 'rubocop-rspec', require: false
end
```

# 導入

```shell
bundle exec rubocop --auto-gen-config
```
をすると、以下の通り`.rubocop_todo.yml`と`.rubocop.yml`とが生成されます。

## .rubocop_todo.yml

```ruby:.rubocop_todo.yml
# Offense count: 2
# Configuration parameters: Blacklist, Whitelist.
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
Rails/SkipsModelValidations:
  Exclude:
    - 'app/controllers/application_controller.rb'
    - 'spec/services/foo_spec.rb'
```
- 既存のコードを解析し、**「違反しているものを一旦無視する」** ために、このファイルが生成されます。
- 違反しない形に修正して、このファイルから該当行を削除していきましょう。
- 後述しますが、可能であれば [ソースコード内で、特定の rubocop の警告を無視する](https://qiita.com/luigiii/items/074e020e07af7ebc872d#%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E5%86%85%E3%81%A7%E7%89%B9%E5%AE%9A%E3%81%AE-rubocop-%E3%81%AE%E8%AD%A6%E5%91%8A%E3%82%92%E7%84%A1%E8%A6%96%E3%81%99%E3%82%8B%E8%A4%87%E6%95%B0%E6%8C%87%E5%AE%9A%E5%8F%AF) とした方が明示的に違反箇所が見えるので望ましいです（数が多い場合には、`.rubocop_todo.yml` を使うしかないかもしれませんが）。


## .rubocop.yml

```ruby:.rubocop.yml
inherit_from: .rubocop_todo.yml # .rubocop_todo.yml が空になったら、この行は削除しましょう。
:
```
- 設定例は、[【Rails】RuboCop 設定編](https://qiita.com/luigiii/items/8a9f5cd4486861819a69) を参照して下さい。
- [デフォルト設定](https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml)
  - デフォルトのコーディングルールは `Ruby Style Guide`（[英語版](https://github.com/rubocop-hq/ruby-style-guide) / [日本語版](https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md)) に基いています。

# 自動修正

```
bundle exec rubocop -A
// or
bundle exec rubocop --auto-correct

// -A をつけない場合、「違反内容の出力」だけされます。
bundle exec rubocop

// ヘルプを見る
bundle exec rubocop --help
```

- 「自動修正」及び「違反内容の出力」をしてくれます。
- 複数項目に違反している場合、一番深刻なものを頭文字1文字で表します。
  - Convention（C）
  - Warning（W）
  - Error（E）
  - Fatal（F）

# [overcommit](https://github.com/sds/overcommit) を使って commit 時に実行されるようにする

### インストール
```ruby:Gemfile
group :development do
  gem 'overcommit'
end
```

### セットアップ
```
bundle exec overcommit --install
bundle exec overcommit --sign
```

### 設定（.overcommit.yml）
```yaml:.overcommit.yml
PreCommit:
  RuboCop:
    enabled: true
    # この行は必ずしも必要ない
    # command: ['bundle', 'exec', 'rubocop', '-c', './.rubocop.yml']
    on_warn: fail # Treat all warnings as failures
```

### 一時的に hook を無効にして commit する場合
```
# 特定の commit を無効にする
SKIP=<hook_command>
e.g. SKIP=RuboCop git commit ...

# 全ての hook を無効にする
e.g. OVERCOMMIT_DISABLE=1 git commit ...
```

# CircleCI を使って git push 時に実行されるようにする

[CircleCI 2.1 設定サンプル（Rails + Rspec + Rubocop + Jest + ESLint + Yarn + Postgres）](https://qiita.com/luigiii/items/8addbc04982dcd40c076#%E8%A8%AD%E5%AE%9A%E4%BE%8B)の以下を参考にして下さい。

- run_rubocop
- rubocop_job

# ソースコード内で、特定の rubocop の警告を無視する（複数指定可）

[rubocopの設定を特定の箇所だけ無効にする](https://docs.rubocop.org/rubocop/configuration.html#disabling-cops-within-source-code)

### 複数行の場合

#### 無視するCop（ルール）を指定する
```ruby
# rubocop:disable Layout/LineLength, Style/StringLiterals
[...]
# rubocop:enable Layout/LineLength, Style/StringLiterals
```

但し、method に対して適応したい場合は、これでも大丈夫です。
`rubocop:disable`だけで`rubocop:enable`は不要です。

```ruby
def method_name # rubocop:disable Metrics/AbcSize
  [...]
end
```

#### 全て無視する
```ruby
# rubocop:disable all
[...]
# rubocop:enable all
```

### 一行の場合

```ruby
for x in (0..19) # rubocop:disable Style/For
```