RuboCopの起動が遅い問題の対策としてのrubocop-daemon

この記事は [Opt Technologies Advent Calendar 2020](https://qiita.com/advent-calendar/2020/opt-technologies) 17 日目記事です
これもまた遅刻しました。何一つ間に合っていない（死）

16 日目の記事は @checche さんの 分析コードの書くコツ or 統計モデリングの実装（未公開） です
18 日目の記事は @___uhu さんの そろそろ競馬AIができそう（未公開） です

---


RubyのLinter兼Formatterとしてデファクトの[RuboCop](https://github.com/rubocop-hq/rubocop) というgemがあります
割とお世話になるんですが、フロントエンドでPrettierやESLintを使ってファイルの保存の度にLint/Formatを実行していた身からすると起動が遅すぎてとてもじゃないけどファイルの保存の度に実行できるような状態じゃありませんでした
世の中には同じような課題感を持った人がいたらしく、[rubocop-daemon](https://github.com/fohte/rubocop-daemon)というツールに出会ったので紹介します

### rubocop-daemonとは

`rubocop-daemon` makes RuboCop faster.

だそうです

RuboCopは起動コストが高いために遅いのが原因のようで、このgemは名前の通りdaemonとしてプロセスに常駐してそこに対策を取る、というライブラリです
参考: https://github.com/rubocop-hq/rubocop/issues/6492#issuecomment-447598459

最低限で利用する場合、 `rubocop-daemon start` で起動して `rubocop-daemon exec` でrubocopの実行をする、という感じです


### エディタで便利に使う

もちろんエディタで便利に使えるようにしたいわけですが、 `rubocop` を流したいときに毎回 `rubocop-daemon start` してから `rubocop-daemon exec` をエディタから出来るようにするのは大変なので、「daemonが起動してなかったら起動をしつつrubocopを実行する」ということをやってくれる `rubocop-daemon-wrapper` を導入します

gemでのinstallをしただけじゃ導入できず、自前で `curl` 使ったりしながら導入する必要があります
ドキュメントの[この項目](https://github.com/fohte/rubocop-daemon#more-speed) にならって以下のようにコマンドを実行し、PATHに `rubocop-daemon-wrapper` の置いてある場所を追加してあげればOKです

```bash
curl https://raw.githubusercontent.com/fohte/rubocop-daemon/master/bin/rubocop-daemon-wrapper -o /tmp/rubocop-daemon-wrapper
sudo mkdir -p /usr/local/bin/rubocop-daemon-wrapper
sudo mv /tmp/rubocop-daemon-wrapper /usr/local/bin/rubocop-daemon-wrapper/rubocop
sudo chmod +x /usr/local/bin/rubocop-daemon-wrapper/rubocop
```

```bash
export PATH="/usr/local/bin/rubocop-daemon-wrapper:$PATH"
```

これで `rubocop` と叩くと `rubocop-daemon-wrapper` を実行してdaemonの立ち上げをしてくれつつ `rubocop` を実行してくれる、という状況を作れました
あとはエディタからこれを叩くようにするだけです

・・・と言うけど意外とめんどくさいのがアレです
普段使っているVSCode、RubyMineについて紹介します

#### VSCode

VSCodeはvscode-rubyプラグインがrubocopコマンドのパスを差し替える機能に対応していないので、 `rubocop` コマンドを `rubocop-daemon-wrapper` へのsymlinkで上書きしてやる必要があります

具体的なやり方はドキュメントの[この項目](https://github.com/fohte/rubocop-daemon#use-with-vs-code) を参照しつつ `rubocop` のパスを探してsymlinkを張り替える、という手順を取ります

```bash
which rubocop  # rvmなど
rbenv which rubocop # rbenv
# => <HOME>/.rvm/gems/ruby-x.y.z/bin/rubocop

ln -fs /usr/local/bin/rubocop-daemon-wrapper $HOME/.rvm/gems/ruby-x.y.z/bin/rubocop
```

以上の手順を踏んで、VSCodeでformatOnSaveを有効化して利用、という形になります

#### RubyMine

RubyMineはそもそもファイル保存時に何か処理するためにはプラグインを入れたりする必要があるので割と手数がいります

- [開いたファイルに対してRuboCopを実行する](https://pleiades.io/help/ruby/rubocop.html#rubocop_external_tool)のドキュメントを元に、 `Tools > External Tools` に以下のような設定でRuboCopを実行するコマンドを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54872/362f55fa-f70c-c6a7-4e33-fbc4286840a7.png)

- ↑で設定したコマンドを実行するだけのマクロを登録する
- `Appearance & Behavior > Quick Lists` から↑で登録したマクロを登録する（↓の画像は `exec rubocop macro` という名前のマクロのみを登録している）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54872/a97440e5-651b-8687-6b61-5f0784bff1c8.png)

- [SaveActions](https://plugins.jetbrains.com/plugin/7642-save-actions) という保存時にコマンドの実行などをさせるプラグインを入れる
- SaveActionsの設定画面でBuild Actionsの項目で `Quick Lists` に登録した処理を登録する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54872/2ff1b560-c336-d02b-e35e-4f293cc221f9.png)

ここまでやってようやくファイル保存時にRuboCopのauto correctが実行できるようになります
（他にもっと楽な方法あったら教えて下さい。。）


### おわりに

というわけでrubocop-daemonの紹介と導入方法でした
快適なRubyライフを送っていくのに役立ててもらえればこれ幸いです