読者です 読者をやめる 読者になる 読者になる

もた日記

くだらないことを真面目にやる

Railsメモ(22) : RuboCopで静的コード解析を行う

Ruby on Rails

github.com

RuboCopというgemを使用すると静的コード解析が行えるようになる(READMEの冒頭にロボコップのセリフが書いてあるようにRoboCopとRubyをかけているのね)。
ベースになっているスタイルガイドは下記ページ(日本語訳)から確認できる。

github.com

RuboCopのインストール


Gemfileに下記行を追加してbundle installする。
これでrubocopコマンドが使えるようになりインストールは完了。

group :development do
  gem 'rubocop', require: false
end


RuboCopの使い方


とりあえずアプリのディレクトリに移動して何も考えずにrubocopコマンドを実行してみると、カレントディレクトリ以下のファイルに対する静的コード解析の結果が出力される。
結果によると45ファイルをチェックして167の違反が見つかったようだ。前半に書いてあるCとかWとかは各ファイルに対する結果で、それぞれ下記内容を示しておりFが最も深刻。
1つずつ結果を確認していけばよいのだろうが数が多く、自動で生成されたコードを対象にしていたり、許容してもよいスタイルもあるので設定を変更してみる。

文字 意味
. Clean(問題なし)
C Convention(慣習違反)
W Warning
E Error
F Fatal
$ rubocop
Inspecting 45 files
.CCCCCCCCCCCCCCWWW.CCCCWWCCC..CCCC.C.CC.C.C.C

Offenses:

Gemfile:3:1: C: Extra blank line detected.
Gemfile:47:81: C: Line is too long. [83/80]
 …省略…
config/routes.rb:9:81: C: Line is too long. [84/80]
  # The priority is based upon order of creation: first created -> highest priority.
                                                                                ^^^^
config/routes.rb:21:81: C: Line is too long. [81/80]
  # Example resource route (maps HTTP verbs to controller actions automatically):
                                                                                ^

45 files inspected, 167 offenses detected


RuboCopの設定


RuboCopの設定はアプリのディレクトリに.rubocop.ymlというファイル名で記述する。
ひとまず今回は数が多くて無視してよさそうなものを設定して再実行してみる。
(なお、デフォルトの設定は下記リンクを参照)

AllCops:
  # 除外するディレクトリ(自動生成されたファイル)
  # デフォルト設定にある"vendor/**/*"が無効化されないように記述
  Exclude:
    - bin/*
    - db/schema.rb
    - db/migrate/*
    - vendor/**/*
  # Rails向けのRails copsを実行。"rubocop -R"と同じ
  RunRailsCops: true

# "Missing top-level class documentation comment."を無効
Style/Documentation:
  Enabled: false

# "Prefer single-quoted strings when you don't need string interpolation or special symbols."を無効
Style/StringLiterals:
  Enabled: false

# "Line is too long"を無効
Metrics/LineLength:
  Enabled: false
$ rubocop
 …
35 files inspected, 17 offenses detected

違反が17にまで減ったので後は1つずつチェックしてみる。

RuboCopの違反内容の例


違反内容の例としては以下のようなものがある。

C: Extra blank line detected.

余分な空白行がある。

C: 1 trailing blank lines detected.

ファイル末尾に余分な空白行がある。

C: Do not use parentheses for method calls with no arguments.
    f.close()
           ^

引数がないメソッドでは()は使用しない。

C: Missing space after #.

コメントの#文字の後に空白がない。

C: Keep a blank line before and after private.

"private"の前後には空白行を入れる。

C: Prefer each over for.

"for"より"each"メソッドの方がよい。
などなど…

一通り修正してrubocopを実行すると以下のように違反が0になった。
RuboCopのおかげでRubyらしい書き方がわかったりするので便利だが、細かすぎると思うこともあるのでその場合は設定で無効化するなどすればよい。

$ rubocop
Inspecting 35 files
...................................

35 files inspected, no offenses detected


.rubocop_todo.yml


もしアプリ開発の途中でRuboCopを追加するなどして違反の数が極端に多い場合は.rubocop_todo.ymlを使うのがよいらしい。
まず、--auto-gen-configオプションを指定して.rubocop_todo.ymlを生成する(例は違反が1つだけ)。

$ rubocop --auto-gen-config
Inspecting 35 files
..................................C

Offenses:

config/routes.rb:3:3: C: Missing space after #.
  #get 'artists/show'
  ^^^^^^^^^^^^^^^^^^^

35 files inspected, 1 offense detected
Created .rubocop_todo.yml.
Run `rubocop --config .rubocop_todo.yml`, or
add inherit_from: .rubocop_todo.yml in a .rubocop.yml file.

生成されたファイルは現状の違反を全て無効化する設定が記述されている。

$ cat .rubocop_todo.yml
# This configuration was generated by `rubocop --auto-gen-config`
# on 2015-08-17 21:07:31 +0900 using RuboCop version 0.32.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.
Style/LeadingCommentSpace:
  Enabled: false

このファイルをinherit_from.rubocop.ymlに追加する。

inherit_from: .rubocop_todo.yml

AllCops:
 …

そうすると違反が0になるので、後は時間があるときにでも1つずつ設定を変更して違反を修正していくという使用方法らしい。

$ rubocop
Inspecting 35 files
...................................

35 files inspected, no offenses detected

パナソニック 密閉型ワイヤレスヘッドホン ブラック RP-WF7-K

パナソニック 密閉型ワイヤレスヘッドホン ブラック RP-WF7-K