コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

Railsでprimary key がid ではない場合 find_each はできない

Model名.all.eachModel名.find_each にしろというのはRubocopでも怒られるド定番な修正対象ですが、できない場合があるのを知らなかったのでメモ

環境

Rails 5.2.1

できないパターン

これができない場合はそもそもRailsのfind系機能が使えないので気づくんですが、ケースとしては…

  • primary_keyが存在しない/設定されていない
  • primary_keyが複合キー

みたいな状態が合致します。

なぜ上記2つの場合できないかというと、実際に範囲指定をしているコードが以下のような内容で、primary_keyを元にとっているからっぽい

def apply_limits(relation, start, finish)
  relation = apply_start_limit(relation, start) if start
  relation = apply_finish_limit(relation, finish) if finish
  relation
end

def apply_start_limit(relation, start)
  relation.where(bind_attribute(primary_key, start) { |attr, bind| attr.gteq(bind) })
end

def apply_finish_limit(relation, finish)
  relation.where(bind_attribute(primary_key, finish) { |attr, bind| attr.lteq(bind) })
end

activerecord/lib/active_record/relation/batches.rb#L262

でprimary_keyは以下みたいな感じ

def primary_key
  options[:primary_key] || default_primary_key
end

def default_primary_key
  "id"
end

rails/schema_definitions.rb at master · rails/rails

そのためRails然としているprimary_key設定であれば勝手にidで引くし、primary_keyが別名設定されていればそれで範囲指定してとっていくはず(ただ取り方を鑑みると整数値しか許容できない気もしますが)

参考リンク