既存のRailsプロジェクトに静的解析ツール(rubocop)を導入する方法

既存のRailsプロジェクトに静的解析ツール(rubocop)を導入する方法

前回NuxtプロジェクトにESlintを導入したので今回はRailsプロジェクト側も同じような静的解析のツールであるrubocopを導入します。

github: https://github.com/rubocop/rubocop

前回の記事: 既存のNuxtプロジェクトにESLintを導入する方法

rubocopインストール

gemfileにrubocopを記述します。開発環境のみチェックすればいいのでgroup debelopmentの中に入れます。

group :development do
  gem 'listen', '~> 3.3'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'rubocop', require: false
  gem 'rubocop-rails', require: false
end

記述できたら bundle install をします。インストールできたら早速チェックします。

api $ rubocop

...詳細が記述される

38 files inspected, 124 offenses detected, 118 offenses auto-correctable

38個のファイルをチェックし124個の違反を検出したみたいです。。

規約違反の修正

下記コマンドで違反の内容を別ファイルに書き出します。

api $ bundle exec rubocop --auto-gen-config

このコマンドで.rubocop.ymlと.rubocop_todo.ymlのファイルが自動で生成されました。

.rubocop_todo.ymlのファイルをみてみます。

# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
Bundler/OrderedGems:
  Exclude:
    - 'Gemfile'

記述の説明すると以下のようになります。

Bundler/OrderedGems: ## Gemの並び順をアルファベット順にする規約
  Exclude:                        ## 検証から除外する
    - 'Gemfile'                   ## ファイル名

一度この記述をコメントアウトしてもう一度rubocopを流します。

api $ rubocop
...

Gemfile:37:3: C: [Correctable] Bundler/OrderedGems: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem rubocop should appear before spring.
  gem 'rubocop', require: false
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

38 files inspected, 1 offense detected, 1 offense auto-correctable

規約に引っかかったので該当コードを修正します。

Before

Gemfile

group :development do
  gem 'listen', '~> 3.3'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'rubocop', require: false
  gem 'rubocop-rails', require: false
end

After

group :development do
  gem 'listen', '~> 3.3'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'rubocop', require: false
  gem 'rubocop-rails', require: false
  gem 'spring'
end

修正できたらもう一度チェックします。

api $ rubocop

Inspecting 38 files
......................................

38 files inspected, no offenses detected

このような感じで一つずつコメントアウトして修正していきます。

規約

Bundler/OrderedGems

先ほど解消した並び順をアルファベットにするという規約です。

Layout/ArgumentAlignment

メソッドの引数のラインを揃えるというものです。

NG
resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]

OK
resource '*',
             headers: :any,
             methods: [:get, :post, :put, :patch, :delete, :options, :head]

Layout/ExtraSpacing

余分なスペースは必要ないという規約です。

NG
config.consider_all_requests_local       = false

OK
config.consider_all_requests_local = false

Layout/SpaceInsideArrayLiteralBrackets

配列内の先頭のスペースのことでデフォルトではスペースは不要という設定になっています。

NG
config.log_tags = [ :request_id ]

OK
config.log_tags = [:request_id]

Layout/EmptyLines

二つ以上の連続した空白は不要という規約です。

NG
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true


# Raises error for missing translations.

OK
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true

# Raises error for missing translations.

Style/ClassAndModuleChildren

クラスとモジュールを入れ子構造にして記述しましょうという規約です。

NG
class ActiveSupport::TestCase
end

OK
module ActiveSupport
  class TestCase
  end
end

Style/Documentation

クラス定義した際にコメントが必要という規約です。

NG 
module Api
  module V1
    class PostsController < ApplicationController

OK
module Api
  module V1
    # PostsController Comments
    class PostsController < ApplicationController

Style/FrozenStringLiteralComment

ファイルの先頭に文字列をfreezeするかの記述をしてくださいというものです。

NG
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

OK
# frozen_string_literal: false

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

この規約を付けようとすると修正箇所が多いので検証の対象から外します。

.rubocop.yml

Style/FrozenStringLiteralComment:
  Enabled: false

上記記述で検証した時に Style/FrozenStringLiteralCommentの規約についてはスルーされます。

Style/GlobalStdStream

STDOUT/STDERR/STDINの代わりに$stdout/$stderr/$stdinを使用するという規約です。

NG
if ENV["RAILS_LOG_TO_STDOUT"].present?
  logger           = ActiveSupport::Logger.new(STDOUT)
  logger.formatter = config.log_formatter
  config.logger    = ActiveSupport::TaggedLogging.new(logger)
end

OK
if ENV["RAILS_LOG_TO_STDOUT"].present?
  logger           = ActiveSupport::Logger.new($stdout)
  logger.formatter = config.log_formatter
  config.logger    = ActiveSupport::TaggedLogging.new(logger)
end

Style/GuardClause

後置IFなどを使用して1行で書きましょうという規約です。

NG
unless @post
  render json: @post, status: 500
end

OK
render json: @post, status: 500 unless @post

Style/StringLiterals

普通の文字列はシングルクォーテーションを使用しましょうという規約です。

NG
require_relative "../config/environment"

OK
require_relative '../config/environment'

Style/SymbolArray

シンボルで構成された配列リテラルは%i記法で記述するという規約です。

NG
resources :posts, only: [:index, :create, :show, :update, :destroy]

OK
resources :posts, only: %i[index create show update destroy]

下記のように全てのチェックが問題なければ完了です。

api $ bundle exec rubocop
Inspecting 37 files
.....................................

37 files inspected, no offenses detected

rubocopファイルの完成形

最終的なrubocopのファイルはこちらです。

AllCops:
  NewCops: enable
  Exclude:
    - 'db/schema.rb'

Style/Documentation:
  Enabled: false

Style/FrozenStringLiteralComment:
  Enabled: false

Railsカテゴリの最新記事