【初心者向け】Railsの品質を上げるRuboCopのインストールと使い方!

RuboCopでRailsの品質管理

Railsで開発を続けていると

「Rubyのこの書き方って正しいのかな?」

「もっと綺麗な書き方があるんじゃないかな?」

「開発メンバーでコードの品質レベルを統一させたい」

いまの書き方に不安になったり、コーディングルールの統一などについて考えると思います。

そんなときに、ぜひ使ってほしいのが「RuboCop」です。

RuboCopは、ソースコードの品質を下げないために使われるRubyのコーディングチェックツールです。

RuboCopを使うことで、誰でも簡単にソースコードの品質を維持できるようになります。

この記事では、RuboCopの導入から使い方までを詳しく紹介します。

RuboCopとは

RuboCopとは、Rubyのコードがコーディング規約に沿っているかを確認できる「静的コード解析ツール(コーディングチェックツール)」の1つです。

RuboCopを使うことで、ソースコードに対して以下のようなチェックをおこないます。(他にもあります)

  • インデント
  • 文字数の長さ
  • メソッド内の行数
  • 条件式の見やすさ
  • ソースコードの複雑度
  • ハッシュなどの末尾にあるカンマの有無

これらのコーディング規約は、自分で追加したり削除したりとカスタマイズすることが可能です。

このような静的コード解析ツールを利用することで、複数メンバーで開発していても、コードを読みやすく品質を維持できるというメリットがあります。

もちろん、1人で開発しているときであっても、綺麗なコードで管理することに越したことはありませんよね。

RuboCopのインストール

RuboCopは、gemで簡単にインストールできます。

Gemfileに以下を追記して、Bundlerでインストールしましょう。

Gemfile
group :development do
        :
        :
  gem 'rubocop', require: false
  gem 'rubocop-rails'
end
RuboCopのインストール
$ bundle install

RuboCopの使い方

RuboCopの使い方は、とっても簡単です。

rubocopコマンドを実行して、ソースコードがRuboCopの規約(ルール)に沿っているかをチェックするだけです。

RuboCopでコードチェック
$ rubocop
Inspecting 49 files
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

Offenses:

config.ru:1:1: C: Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
# This file is used by Rack-based servers to start the application.
^
     :
     :
test/test_helper.rb:6:81: C: Metrics/LineLength: Line is too long. [82/80]
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
                                                                                ^^

49 files inspected, 166 offenses detected

おそらく、めちゃくちゃ警告が出たと思います!

このままの状態でRuboCopの警告をスルーするのは、ちょっと難しそうですね。

RuboCopの設定ファイルについて

本来であれば、RuboCopで警告された対象コードを確認し、しっかり対応するのがベストです。

ですが、RuboCopはデフォルトだとコーディング規約が厳しいうえにチェック範囲も広く、ライブラリなど実際に触れないファイルに関しても対象にしてしまいます。

普段、あまり触らないコードやファイルは除外したいですよね。

そこで、--auto-gen-configオプションを使って、RuboCopのルールをカスタマイズするための「設定ファイル」を作ってみましょう。

RuboCopの設定ファイルを作成
$ rubocop --auto-gen-config
Added inheritance from `.rubocop_todo.yml` in `.rubocop.yml`.
Phase 1 of 2: run Metrics/LineLength cop
Inspecting 49 files
.CC.....................C..CCC..CC.C...C...CCC..C

49 files inspected, 64 offenses detected
Created .rubocop_todo.yml.
Phase 2 of 2: run all cops
Inspecting 49 files
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC.CCCCCCCCCCCCC

49 files inspected, 102 offenses detected
Created .rubocop_todo.yml.

上のコマンドを実行すると、以下の2つのファイルが作成されます。

  • 「.rubocop.yml」…コーディング規約を設定するファイル
  • 「.rubocop_todo.yml」…規約を無視するための設定ファイル

.rubocop.ymlは、独自のコーディング規約を設定するためのファイルです。

現段階では、規約を定義するような記述はありませんが、代わりに以下のような.rubocop_todo.ymlを読み込む記述があります。

.rubocop.yml
inherit_from: .rubocop_todo.yml

.rubocop_todo.ymlは、現状は対応できない規約を一時的にスルーするための設定が書かれたファイルです。

そのため、最終的にはこのファイルの中身を空にすることが望ましいです。

ただし、現段階では「rubocopコマンドで出た警告をすべてスルーする」というような内容の記述がすでに書かれているはずです。

そのため、この状態でrubocopコマンドを実行すると、以下のように警告が1つも出ない状態になります。

規約に沿ったコードになっていることを確認
$ rubocop
Inspecting 49 files
.................................................

49 files inspected, no offenses detected

キツネ

最終的にはこのような状態になるソースコードを目指すよ!

RuboCopの設定ファイルを変更

このままRuboCopを使い続けても、警告をすべてスルーする設定になっているため、まったく意味がありません。

そこで、もう少し現実的な設定にしてみます。

不要なコーディング規約や関係のないファイルを除外し、使いやすいコーディングチェックの設定に変更してみましょう。

ここでは.rubocop.ymlを以下のように設定しました。これはあくまで例なので、自分で調べながらカスタマイズしてみてくださいね。

また、.rubocop_todo.ymlの中身はすべて削除し、空にすることを忘れずに。

.rubocop.yml
# 将来的には対応する規約の読込
inherit_from: .rubocop_todo.yml

# 追加した規約ファイル読込
require:
  - rubocop-rails

AllCops:
  # Rubyバージョン指定
  TargetRubyVersion: 2.6
  # 除外
  Exclude:
    - 'config.ru'
    - 'bin/**'
    - 'lib/**'
    - 'db/**/*'
    - 'config/**/*'
    - 'script/**/*'
    - !ruby/regexp /old_and_unused\.rb$/

# 日本語でのコメントを許可
AsciiComments:
  Enabled: false

# クラスのコメント必須を無視
Documentation:
  Enabled: false

# モジュール名::クラス名の定義を許可
ClassAndModuleChildren:
  Enabled: false

# 文字リテラルのイミュータブル宣言を無視(freezeになるのはRuby3以降)
Style/FrozenStringLiteralComment:
  Enabled: false

キツネ

現実的じゃないコーディング規約は除外することも大切だよ!

RuboCopでファイルを自動修正

RuboCopのコーディング規約の設定が終わったら、rubocopコマンドを実行してみてください。警告の数がかなり減ったことに気付くはずです。

減ったとはいえ、すべて手作業で修正するのも面倒です。簡単なものはRuboCopに直してもらいましょう。

RuboCopには、警告している箇所を自動で修正してくれる機能があり、--auto-correctオプションを使うことで、ある程度は自動で警告を修正してくれます。

「ある程度」というのは、RuboCopではどう修正していいのか判断できないところもあり、その場合はスキップされるという意味です。

RuboCopが自動修正できた箇所は「Corrected」と表示されます。

RuboCopの警告を自動で修正
$ rubocop --auto-correct
Inspecting 19 files
CC..............C.C

Offenses:

Gemfile:44:81: C: Metrics/LineLength: Line is too long. [83/80]
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
                                                                                ^^^
Gemfile:45:28: C: [Corrected] Style/SymbolArray: Use %i or %I for an array of symbols.
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
Gemfile:49:81: C: Metrics/LineLength: Line is too long. [98/80]
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
                                                                                ^^^^^^^^^^^^^^^^^^
Gemfile:51:3: C: [Corrected] Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem listen should appear before web-co
nsole.
  gem 'listen', '>= 3.0.5', '< 3.2'
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Gemfile:52:81: C: Metrics/LineLength: Line is too long. [130/80]
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
                                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Gemfile:54:3: C: [Corrected] Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem rubocop should appear before sprin
g.
  gem 'rubocop', require: false
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Gemfile:55:3: C: [Corrected] Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem rubocop should appear before sprin
g-watcher-listen.
  gem 'rubocop', require: false
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Gemfile:67:31: C: [Corrected] Style/SymbolArray: Use %i or %I for an array of symbols.
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Rakefile:2:81: C: Metrics/LineLength: Line is too long. [90/80]
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
                                                                                ^^^^^^^^^^
test/application_system_test_case.rb:1:9: C: [Corrected] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
require "test_helper"
        ^^^^^^^^^^^^^
test/test_helper.rb:6:81: C: Metrics/LineLength: Line is too long. [82/80]
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
                                                                                ^^

19 files inspected, 11 offenses detected, 6 offenses corrected

キツネ

簡単なリファクタリングでも数が多いと面倒だよね!楽しよう!

RuboCopのリファクタリング手順

RuboCopの自動修正が終わったら、もういちどrubocopコマンドを実行してみてください。

おそらく、いくつかの警告がまだ表示されるはずです。

自動修正後の警告
$ rubocop
Inspecting 19 files
CC................C

Offenses:

Gemfile:44:81: C: Metrics/LineLength: Line is too long. [83/80]
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
                                                                                ^^^
Gemfile:49:81: C: Metrics/LineLength: Line is too long. [98/80]
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
                                                                                ^^^^^^^^^^^^^^^^^^
Gemfile:52:81: C: Metrics/LineLength: Line is too long. [130/80]
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
                                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Rakefile:2:81: C: Metrics/LineLength: Line is too long. [90/80]
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
                                                                                ^^^^^^^^^^
test/test_helper.rb:6:81: C: Metrics/LineLength: Line is too long. [82/80]
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
                                                                                ^^

19 files inspected, 5 offenses detected

この実行結果を見ると、警告が全部で5カ所でていますが、すべて「コメントの文字数が長すぎる」というものです。

これらのコメントが不要であれば、対象ファイルからコメントを削除してしまいましょう。

このようにRubCcopを実行、修正するという手順を繰り返し、ソースコードの品質を下げないようにするのが基本です。

そして、RuboCopの実行結果が最終的に以下のような状態になれば、ソースコードの品質が保たれていることになります。

コードの品質が保たれている状態
$ rubocop
Inspecting 19 files
...................

19 files inspected, no offenses detected

キツネ

Gitにコミットする前にRuboCopを実行する癖をつけようね!

RuboCopでRailsのコーディング規約を設定する際の注意点

もし、rubocopを実行時に、Warning: unrecognized cop Rails found in .rubocop.ymlのようなエラーが出てしまった場合は、以下のような設定をしている可能性があります。

.rubocop.yml
# バージョン0.72以降は使えないので注意
Rails:
  Enabled: true

コメントにも書いてあるとおり、RuboCopのバージョンが0.72以降は「Rails Cops」が使えなくなりました。

RuboCopのバージョンが0.72以降の場合は、rubocop-railsgemでインストールし、.rubocop.ymlrequire: rubocop-railsを追記してください。

キツネ

この記事を上から順に実行してきた人は問題ないと思うよ!

まとめ

コーティングのルールは、会社やプロジェクトによっても違うと思います。

開発メンバーとも相談し、現実的なラインで使い続けられるルールを設定するといいです。

また、RuboCopを使うことでRubyでの色々な記述方法を知ることができるので、Rubyを勉強し始めた方にもおすすめです。

ぜひ、RuboCopを導入して、快適なプログラミング生活を送ってください!

テキストのコピーはできません。