Let's write β

プログラミング中にできたことか、思ったこととか

rubocop-railsのfind_by_*系メソッドの自動修正をstaticに定義した一部のメソッドの上で無効にする

Railsで開発するにあたって、rubocop-railsをLinterとして利用しており、 自動修正機能を適用したときにエラーに繋ってしまったのでメモしておきます。

背景

Railsではfind_by_idfind_by_nameのように、ActiveModelのカラム名を利用して検索できるメソッドが動的に定義されます。

しかし、このような個別のメソッドを利用するのではなくfind_by形式に統一するスタイルがRuboCopにおいては推奨されており、検知&自動修正するためのCopが存在します

一方で、自前でfind_by_hogeのようなメソッドを定義した場合にもこのCopの判定対象になってしまい、自動修正の対象になってしまいます。

自分の開発しているプロジェクトでは自動修正をかけた際に意図せず変更されてしまい、メソッド未定義のエラーに繋りました。

回避方法

一部のメソッドをこのCopの対象から除外したい場合には以下のアプローチがあります:

  • 該当行にコメントで rubocop:disable Rails/DynamicFindBy を追加する
  • rubocop.yml中で該当メソッド名をホワイトリストに追加する

2つの方法があるなかで、私は後者の選択をしました。

判断の理由としては、前者のインラインコメントで都度対応をするという方法は

  • 実装者がコメントの追加を忘れやすい(コードレビューでも指摘忘れやすい)
  • 後からコードを読むメンバーにコメントの背景が伝わりづらい
  • 呼びだしの箇所で個別に記述するコストがかかる

といったいくつかのデメリットがあると考えたためです。

そのため、後者の.rubocop.yml 中に記述するアプローチを取りました。

Rails/DynamicFindBy:
  Whitelist:
    - find_by_sql
    - find_by_hoge

Whitelistに該当メソッドだけでなく、find_by_sqlについても追加していますが、こちらのメソッドもRailsの標準のメソッドであり自動修正の対象とはしたくないためです。

RuboCopの設定は、デフォルトの設定を自動的に継承するようになっていますが、

継承されている設定と同じ項目についての設定を記述した時に以下のようなルールで上書きがされます。

  • ハッシュマップはデフォルトの物とマージされ、衝突したキーについては最後の設定で上書きされる
  • 配列については常に最後の設定によって上書きされる

(参考: Configuration - RuboCop: The Ruby Linter that Serves and Protects)

今回は後者の配列の上書きに該当しますので、標準でWhitelistに追加されているfind_by_sqlについても自分で追加しておく必要がありました。