kasei_sanのブログ

かせいさんのIT系のおぼえがきです。胡乱の方はnoteとtwitterへ

scope は、戻り値が `nil` や `false` のときも `ActiveRecord::Relation` を返す

条件式付きのscpoeをクラスメソッドに移行する際に、問題になる

例: scopeの場合

class Item < ApplicationRecord
  scope :by_name, -> name { where('name like ?', "%#{name}%") if name.present? }
end

引数の値が nil でも、 ActiveRecord::Relation がキチンと返ってくる

Item.by_name(nil).order(:created_at) #=> ActiveRecord::Relation

例: クラスメソッドの場合

class Item < ApplicationRecord
  def self.by_name(name)
    if name.present?
      where('name like ?', "%#{name}%")
    end
  end
end

この場合、Item.by_namenil を渡すとエラーが発生する

Item.by_name(nil).order(:created_at) #=> NoMethodError: undefined method `order' for nil:NilClass

どうすればよいの?

nil の代わりに all を返せば ActiveRecord::Relation が返るようになる

  def self.by_name(name)
    if name.present?
      where('name like ?', "%#{name}%")
    else
      all
    end
  end
Item.by_name(nil).order(:created_at) #=> ActiveRecord::Relation