MENU
カテゴリー

RuboCopの「Assignment Branch Condition size for search is too high」エラーの原因と対処法

  • URLをコピーしました!
目次

このエラーの正体

Assignment Branch Condition size for search is too high. [<10, 21, 5> 23.79/20]

Rails開発中に、RuboCopからこのようなエラーが出た。読んでみると「searchメソッドのABCサイズが大きすぎる」という指摘のようだ。このエラーの意味と、実際に行った対処方法を整理しておく。

RuboCopとは

GitHub
GitHub - rubocop/rubocop at v0.28.0 A Ruby static code analyzer and formatter, based on the community Ruby style guide. - rubocop/rubocop

RuboCopはRuby用の静的コード解析ツールで、コードの長さやインデント、命名規則など、スタイルの乱れを検出して教えてくれる。指摘によっては自動修正してくれるものもあるが、設計に関わる指摘は自分で判断して直す必要がある。RuboCopの指摘がすべて自分のコードに当てはまるとは限らないので、内容を理解した上で対応することが大事。

ABCサイズとは何か

今回の警告は「Metrics/AbcSize」というRuboCopのルールによるもの。ABCサイズとは、1つのメソッド内にある代入(Assignment)、メソッド呼び出しなどの分岐(Branch)、条件分岐(Condition)の数から計算される複雑度の指標。数値が大きいほど、そのメソッドが多くのことをやりすぎている可能性が高い。エラー文の[<10, 21, 5> 23.79/20]は、A=10、B=21、C=5から算出したスコアが23.79で、設定上の上限(Max)20を超えている、という意味になる。

実際に指摘されたコード

指摘を受けたのは以下のsearchメソッド。

  def search
   if params[:city_id]
     pagy, offices = pagy Office.where(city_id: params[:city_id])
     pagy_headers_merge(pagy)
   elsif params[:keyword]
     keywords = params[:keyword].split(/[[:blank:]]+/).select(&:present?)
     pagy, offices = pagy_array([])
     keywords.each do |keyword|
       offices += Office.where('name LIKE (?) OR
                                address LIKE (?) OR
                                near_station LIKE (?) OR
                                introduction LIKE (?) OR
                                company LIKE (?)',
                               "%#{keyword}%",
                               "%#{keyword}%",
                               "%#{keyword}%",
                               "%#{keyword}%",
                               "%#{keyword}%")
     end
   else
     pagy, offices = pagy(Office.all)
     pagy_headers_merge(pagy)
   end
   render json: offices, each_serializer: OfficeIndexSerializer, include: '**'
 end

if / elsif / else の分岐が多く、さらにelsifの中にeachやOffice.whereなど複数の処理が詰め込まれている。縦に長いコードで、ABCサイズが上がりやすい典型的な形になっていた。

対処方法

今回はひとまず、.rubocop.ymlの設定を変更して警告を回避する方法を選んだ。

Metrics/AbcSize:
 # The ABC size is a calculated magnitude, so this number can be a Fixnum or
 # a Float.
 Max: 15 

デフォルトのMaxは15になっていたので、これを25に変更してコミット。これでRuboCopからの指摘は出なくなった。

ただ、これはあくまで警告を黙らせるための対処であって、コードの複雑さそのものは解決していない。本来であれば、if / elsifの分岐ごとに別メソッドへ切り出したり、検索条件の組み立てをオブジェクトやスコープに委譲したりして、searchメソッド自体をシンプルにするのが望ましい対応だと思う。Maxの数値変更はあくまで最終手段として、まずはリファクタリングを検討したい。

まとめ

RuboCopの「Assignment Branch Condition size for search is too high」は、メソッドの代入・分岐・条件の数から算出されるABCサイズが上限を超えたときに出る警告。.rubocop.ymlのMetrics/AbcSizeのMax値を変更すれば一時的に回避できるが、根本的にはメソッドを分割してシンプルにすることが望ましい。設定でも変更できるということを知っておくと、対応の選択肢が広がるはず。

Qiita

Qiita
@m6mmsf's My Page - Qiita 記事投稿数: 138 Contribution: 414 フォロワー数: 22

Qiitaでも記事を書いています。

関連記事

よかったらシェアしてね!
  • URLをコピーしました!
目次