以下のdestroy_all_safelyメソッドのように、where条件で返されるレコードに作用するクラスメソッドを定義することを考える.
destroy_all_safelyメソッドではeachメソッドを使って各インスタンスに処理を行うメソッドとする.
class User < ActiveRecord::Base
class << self
def call_singleton_method
User.where(id: [1, 2, 3]).destroy_all_safely
end
end
end
以下のようにクラスメソッドにするとeachがundefined method for と怒られる.
class User < ActiveRecord::Base
class << self
def destroy_all_sefely
each do |user| # => undefined method
# some processes to be safe
end
end
end
end
いくつかの実装方法があるがActiveRecord_Relationクラスをオープンしてメソッドを定義すると上手くいく.
これはUser.where(id: [1, 2, 3])で評価される結果が、User::ActiveRecord_Relationクラスのインスタンスになっているからである.
User.where(id: [1, 2, 3]).class # => User::ActiveRecord_Relation
class User < ActiveRecord::Base
class ActiveRecord_Relation
def destroy_all_safely
each do |user|
# it works
end
end
end
end
別解
オープンクラスが仰々しいという場合は以下のようにクラスメソッド内でallを呼ぶことでもできる
class User < ActiveRecord::Base
class << self
def destroy_all_safely
all.each do |user|
# it works
end
end
end
end