LoginSignup
8

More than 5 years have passed since last update.

Railsのモデルのクラスメソッド内でeachを使うときのメソッドの定義の仕方

Posted at

以下の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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8