ActiveRecordのscopeの中でTime.nowを使ったときに起こる問題
model の中で scope を使うときに今の時間を比較してレコードをとってきたい場合に時間が固まってしまうことがある
developmentモードでは起こらずproductionモードのみで起こる。
今日登録したユーザーを表示したいとなった場合
class User < ActiveRecord::Base scope :today_scope, where("users.created_at BETWEEN :start_time AND :end_time", { start_time: Time.now.beginning_of_day, end_time: Time.now.end_of_day }) end
上記をproductionモードで走らせると起動した時間でTime.nowが固まってしまうため、ずっと起動しっぱなしで次の日になった場合正確な情報はとれない
正確な情報を取る場合はlambdaを使う
class User < ActiveRecord::Base scope :today_scope, lambda{ where("users.created_at BETWEEN :start_time AND :end_time", { start_time: Time.now.beginning_of_day, end_time: Time.now.end_of_day })} end
これで今日登録したユーザーはとってこれる。
ちなみに以下のソースでも固まってしまうので注意が必要
class User < ActiveRecord::Base DISABLE = 0 ACTIVE = 1 scope :today_scope, lambda{ where("users.created_at BETWEEN :start_time AND :end_time", { start_time: Time.now.beginning_of_day, end_time: Time.now.end_of_day })} scope :active, today_scope.where(status: User::ACTIVE) end
@users = User.active.all
activeのscopeにlambdaがついていない状態でtoday_scopeを使うとtoday_scopeのlambdaは有効にならず時間が固まってしまう。
class User < ActiveRecord::Base DISABLE = 0 ACTIVE = 1 scope :today_scope, lambda{ where("users.created_at BETWEEN :start_time AND :end_time", { start_time: Time.now.beginning_of_day, end_time: Time.now.end_of_day })} scope :active, lambda{ today_scope.where(status: User::ACTIVE) } end
activeにもlambdaを使うことによって時間は固まらなくなる
lambdaは->で書いた方が見やすいと思うので->を使った方がいいと思う