您可以在 Rails 3 搜索中对日期进行比较吗?
Posted
技术标签:
【中文标题】您可以在 Rails 3 搜索中对日期进行比较吗?【英文标题】:Can you do greater than comparison on a date in a Rails 3 search? 【发布时间】:2011-05-12 14:17:48 【问题描述】:我在 Rails 3 中有这个搜索:
Note.where(:user_id => current_user.id, :notetype => p[:note_type], :date => p[:date]).order('date ASC, created_at ASC')
但我需要 :date => p[:date]
条件等同于 :date > p[:date]
。我怎样才能做到这一点?感谢阅读。
【问题讨论】:
【参考方案1】:Note.
where(:user_id => current_user.id, :notetype => p[:note_type]).
where("date > ?", p[:date]).
order('date ASC, created_at ASC')
或者您也可以将所有内容转换为 SQL 表示法
Note.
where("user_id = ? AND notetype = ? AND date > ?", current_user.id, p[:note_type], p[:date]).
order('date ASC, created_at ASC')
【讨论】:
安全吗?我的意思是如果 p[:date] 来自用户输入,它会导致 SQL 注入吗? 因为where()
所以很安全。使用where()
会自动转义输入。
Simone 的评论并不完全正确; where()
以上面显示的格式使用输入时自动转义输入,用问号代替变量,然后在函数调用中列出它们。以这种方式使用它是不安全的:Note.where("date > #p[:date]")
另外值得注意的是,在合并具有user_id
字段的模型的情况下,使用where("user_id = ?",current_user.id)
比where(user_id: current_user.id)
风险更大。使用原始 SQL 表示法意味着您需要自己包含表格说明,例如:where("notes.user_id = ?",current_user.id)
。
你应该小心这个,因为时区。当你使用 where with "" Rails 直接进入数据库,并且在数据库中日期以 UTC 格式保存,但你应该以 UTC + 5 为例,这是不正确的。因此,请确保在执行之前将 p[date] 转换为您当前的 UTC【参考方案2】:
如果遇到列名不明确的问题,您可以这样做:
date_field = Note.arel_table[:date]
Note.where(user_id: current_user.id, notetype: p[:note_type]).
where(date_field.gt(p[:date])).
order(date_field.asc(), Note.arel_table[:created_at].asc())
【讨论】:
由于某种原因,我在 PostgreSQL 服务器上使用 Simone 的“where”方法找不到列时出现错误,但它在 SQLite 中有效。你的方法对两者都有效。【参考方案3】:你可以尝试使用:
where(date: p[:date]..Float::INFINITY)
等价于sql
WHERE (`date` >= p[:date])
结果是:
Note.where(user_id: current_user.id, notetype: p[:note_type], date: p[:date]..Float::INFINITY).order(:fecha, :created_at)
我也变了
order('date ASC, created_at ASC')
对于
order(:fecha, :created_at)
【讨论】:
【参考方案4】:如果您不喜欢传入字符串,我更喜欢@sesperanto 的做法,除了让它更简洁之外,您可以将Float::INFINITY
放在日期范围内,而只需使用created_at: p[:date]..
Note.where(
user_id: current_user.id,
notetype: p[:note_type],
created_at: p[:date]..
).order(:date, :created_at)
请注意,这会将查询更改为 >=
而不是 >
。如果这是一个问题,您总是可以通过运行 p[:date] + 1.day..
之类的东西来为日期添加一个时间单位
【讨论】:
【参考方案5】:更新
Rails 核心团队决定暂时恢复此更改,以便更详细地讨论它。请参阅this comment 和this PR 了解更多信息。
我仅出于教育目的而留下我的答案。
Rails 6.1 中用于比较的新“语法”(已还原)
Rails 6.1 为where
条件下的比较运算符添加了新的“语法”,例如:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
所以你的查询可以改写如下:
Note
.where(user_id: current_user.id, notetype: p[:note_type], 'date >', p[:date])
.order(date: :asc, created_at: :asc)
这里是a link to PR,您可以在其中找到更多示例。
【讨论】:
PR 已恢复,因此这在 Rails 中暂时不起作用。 new PR 目前正在进行中。 谢谢,@PaulB。我已经更新了我的答案。以上是关于您可以在 Rails 3 搜索中对日期进行比较吗?的主要内容,如果未能解决你的问题,请参考以下文章