LoginSignup
17
13

More than 3 years have passed since last update.

ぼくがかんがえる、さいてきにむかうRubocop

Last updated at Posted at 2017-01-05

Railsプロジェクトのコードをきれいに保つために、Rubocopを使っています。ただし、既存のスタイルそのままではなく、プロジェクトに合わせて各種の変更を行いつつ運用しています。

大原則

まず、運用ルールとして、「Rubocopの評価は行うけど、コミットを止めたりはしない」という方針で運用しています。というのも、(もちろん構文エラーがあるなど、どうしようもないものについては別途考えないといけないかもしれませんが)コミットを止めてしまうぐらいに強制すると、急ぎのときに「なんとかその場しのぎで(ルールだけ通過させる/ルール自体を一時停止させてしまう)」、より対応困難なコードを生む危険性があると考えたからです1

機能拡張とコード整理を別に行うということで、このようにゆるふわでやっていくのがいいのかなと思っています。

おことわり

説明の都合上、実際の.rubocop.ymlではひとまとめに書いている部分を分解していることがあります。

初期設定

まずは、.rubocop.ymlでRubyのバージョン設定などをしておきます(バージョンが上がれば、文法やメソッドが変化していきます)。

初期設定
AllCops:
  TargetRubyVersion: 2.2

# Rails用の設定を有効化
Rails:
  Enabled: true

とりあえずこれで動くようにはなりますが、とはいえこのままでは過剰にかかる部分も多いので、適宜調整して行かなければいけません。

真っ先に止めるもの

まず、Railsが自動生成する、Bundlerでインストールするなどで、人の手で変更しないことが前提のファイルは、問題点を指摘されても対応不能ですので、チェックの対象から外しておきます。

AllCops:
  Exclude:
    - bin/*
    - db/schema.rb
    - vendor/**/*

そして、Gemとしてなど全世界に公開するプロジェクトならともかく、開発もユーザーも日本人、というようなRailsシステムでは、コメントに日本語を書けないのは邪魔にしかならないので、Style/AsciiCommentsも問答無用で停止します。

Style/AsciiComments:
  Enabled: false

特殊なファイルには特殊な設定

Railsでは、メインのプログラムを書くapp/以下以外にもコードを書く場所があります。たとえば、db/migrate/以下に書くマイグレーションは、10カラムを越えるようなテーブルを作っただけで行数やABCサイズが限界値を超えてしまいます。そして、これを複数のメソッドに分けるというのも非効率なだけで意味がありません。さらに、(内部でデータ移行を行うなど凝ったものを作るのでもない限り)マイグレーションの内容はクラス名や中身で明らかですし、マイグレーションクラスを他のコードに使うこともないので、ドキュメントコメントの必要性も薄くなります。ということで、これだけの設定を止めました。

Documentation:
  Exclude:
    - 'db/migrate/*'

Metrics/MethodLength:
  Exclude:
    - 'db/migrate/*'

Metrics/AbcSize:
  Exclude:
    - 'db/migrate/*'

また、初期データ用にseed-fuを使っていますが、データリストはRubyコードとは言えあくまでデータの管理用なので、ケツカンマを認めてあとから追記をやりやすくしたほうが運用上便利ということで、ここだけ外しています。

Style/TrailingCommaInArguments:
  Exclude:
    - 'db/fixtures/*'

スタイル設定

分量設定

メソッド長とかABCサイズとかは、デフォルト設定だときついように思うかもしれませんが、慣れれば案外書けるようになります。ただ、80桁制限はきつすぎるので、100桁まで緩和してあります2

Metrics/LineLength:
  Max: 100

コーディングスタイル

字下げはともかく(private以降を下げるRailsスタイル)、空行は多少入っていてもいなくても読みやすさにそこまで大きく影響するものではないと、全部止めてしまいました。

Style/IndentationConsistency:
  EnforcedStyle: rails

Style/EmptyLines:
  Enabled: false

Style/EmptyLinesAroundClassBody:
  Enabled: false

Style/EmptyLinesAroundModuleBody:
  Enabled: false

Style/EmptyLinesAroundMethodBody:
  Enabled: false

Style/EmptyLinesAroundBlockBody:
  Enabled: false

好みの問題

パーセントリテラルの区切り文字も特定のものを推奨してきますが(Style/PercentLiteralDelimiters)、(正規表現以外では)好みで縦棒区切りを使っています。

Style/PercentLiteralDelimiters:
  PreferredDelimiters:
    '%i': '||'
    '%w': '||'
    '%W': '||'

似て非なるもの

モジュールメソッド的なもの

以前記事にまとめましたが、SomeModule.some_methodのように呼べるメソッドは、extend selfmodule_functionのどちらでも作れます。Rubocopにもどちらかを推奨させるオプション(Style/ModuleFunction)があります…が、この2つは挙動が異なります。意識して使い分けたいので、これは停止させてあります。

Style/ModuleFunction:
  Enabled: false

一部箇所だけ止める

Style/NilComparisonは、a == nilではなくa.nil?と書く、という設定です。ふつうは問題ないのですが、ActiveRecordのSQLをDSLで書けるbaby_squeelcolumn_name == nilでしか動かないので、それを使う箇所だけ、# rubocop:disable Style/NilComparisonのようなコメントを入れて止めています。

あと、二重否定(!!)を使わない、というStyle/DoubleNegationもあります。普段の条件判定に使う必要はほぼないのですが、?で終わるメソッドの返り値としてtruefalseかだけを渡したい、というシチュエーションでは便利なので、そういう箇所だけ限定的に解除しています。

新しい設定を取り入れる

他のオブジェクトのメソッドを呼ぶ.sendですが、Ruby 1.9以降はpublic_sendが登場しています。そこで、「パブリックでいいのならpublic_send」「privateが必要なら__send__」というように使い分けさせる、というStyle/Sendがあります。この世界観に納得して、そして自動では入らないのであえてonにして運用しています3

まとめに代えて

Rubyとして処理させる以上、(どれだけ納得できなくても)文法は守らないと動きませんが、そうでないコーディング規約には、設定するだけの理由があります。以前にまとめましたが、このようなルールに対して「盲目的に従う」のも「守らなくても動くからと、ただ無視する」のも、同じように危険な行為だと思います。

前々からそんなことを考えつつRubocopの設定をテーマに書いてみようと思ったところに、JavaScriptでの強烈かつ天下り的なルール設定があったので、自分も記事にした次第です。


  1. 趣味で作っている別件のコードでは、Travis CIにRubocopも組み込んで、「1件でもあればテスト失敗」とするようにしてあることもあります。 

  2. 別に入れたGemが長いコメントを生成してしまうので、どうしたものか少々悩んでいます。 

  3. ソケット系など、まったく別なsendを使う場合は、素直にオフとしたほうが良さそうです。 

17
13
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13