このエントリーをはてなブックマークに追加
2013-08-06 23:58:00 +0900

RailsのActiveRecordでひさびさにハマったのでメモ。 ドキュメントにもあるように,ActiveRecordのscopeという宣言のように使うクラスメソッドについて。

Adds a class method for retrieving and querying objects.

Note that this is simply ‘syntactic sugar’ for defining an actual class method

とあるように、ActiveRecordのscopeはモデルクラスのクラスメソッドを作成するための便利メソッドなんだけど,罠があって,以下のような使い方は間違いというお話.

Note that scopes defined with scope will be evaluated when they are defined, rather than when they are used. For example, the following would be incorrect:

class Post < ActiveRecord::Base
  scope :recent, where('published_at >= ?', Time.current - 1.week)
end

The example above would be ‘frozen’ to the Time.current value when the Post class was defined, and so the resultant SQL query would always be the same. The correct way to do this would be via a lambda, which will re-evaluate the scope each time it is called:

以下のようにlambdaを使うというのが1パターン。

class Post < ActiveRecord::Base
  scope :recent, lambda { where('published_at >= ?', Time.current - 1.week) }
end

あとは、素直に以下のようなクラスメソッドを作れば回避可能。

def self.recent
  self.where('published_at >= ?', Time.current - 1.week)
end



記事一覧へ