如何在.where()
中访问对象的属性?
我正在尝试运行这行代码:
Task.where("(created_at <= ?", Time.now - <deadline>).update_all(expired: true)
这个想法是,任何创建日期超过设定截止日期(现在时间 - 截止日期)的任务都会将其expire属性设置为true。
问题是:deadline
是Task的一个属性,每个任务都有自己的截止日期。所以我需要.where()
检查以下逻辑:对于任何给定的Task对象,如果created_at小于Time.now减去(这是我坚持的部分),而不是设置它已过期属性为true
伪代码:
Task.where( Task's created_at attr is <= to the current time - Tasks's deadline attr ).update_all( set Task's expired attr to true )`
我需要访问对象的属性作为.where()
中逻辑的一部分。
我的其他一些尝试:
Task.where("(created_at <= ?", Time.now - :deadline).update_all(expired: true)
TypeError:无法将符号转换为确切的数字
Task.where("(created_at <= ?", Time.now - self.deadline).update_all(expired: true)
NoMethodError:未定义的方法`截止日期&#39; for main:Object
Task.where("(created_at <= ?", Time.now - params[:deadline]).update_all(expired: true)
NameError:未定义的局部变量或方法`params&#39; for main:Object
编辑:
create_table "tasks", force: :cascade do |t|
t.string "name"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "expired", default: false
t.integer "deadline", default: 604800
end
我在开发模式下运行rails,所以我认为数据库是SQL, 截止日期属性应为整数(使用7.days或实际值创建)
答案 0 :(得分:1)
取决于您的数据库:
date_default_timezone_set('UTC');
$month = date('Ym');
$lastmonth = date('Ym', strtotime('first day of -1 month');
date_default_timezone_set('UTC');
$dt = new DateTime();
$month = $dt->format('Ym');
$dt2 = $dt; // to save $dt for later use
$lastmonth = $dt2->modify('first day of -1 month')->format('Ym');
Task.where('created_at + (deadline * "1 second::INTERVAL") <= ?', Time.now)
注意:以上内容未经测试。我只是按照&#34;添加日期功能&#34;的等效语法。对于上面不同的数据库来自各自的文档页面
Arel可以正常工作,但在将Task.where('DATE_ADD(created_at, INTERVAL deadline SECOND) <= ?', Time.now)
从秒转换为&#34;持续时间&#34 ;;您可能会找到一种方法来继续以下不完整的表达式:
Task.where('DATEADD(second, deadline, created_at) <= ?', Time.now)
答案 1 :(得分:1)
请记住,解决方案依赖于数据库类型,因此适用于SQLite(如果你已经采用了rails默认值,可能适配器)可能不适用于MySQL或PostgreSQL。例如,如果您决定部署到Heroku,那么您的数据库将是PostgreSQL。
您说您正在为development
环境寻找解决方案,所以听起来这是您正在开发但尚未部署的代码?
如果是这样,我建议您更改或更改数据库布局以添加日期时间列expires_at
并添加回调方法以在您保存记录时设置它。
class Task < ApplicationRecord
before_save :update_expires_at
private
def update_expires_at
self.expires_at ||= Time.now + 7.days
end
end
这会让你做...
Task.where("(expires_at <= ?", Time.now).update_all(expired: true)
但我甚至不确定您是否需要expired
列,除非您可能想要将记录设置为手动过期。你可以在课堂上有一个方法......
def expired?
expires_at <= Time.now
end
您可以为已过期或未过期的
创建范围class Task < ApplicationRecord
scope :expired, -> {where('expired_at <= ?', Time.now)}
scope :active, -> {where('expired_at > ?', Time.now)}
只需使用范围。
@my_expired_tasks = Task.expired