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