Les*_*leh 3 activerecord ruby-on-rails
如何在日期时间中选择具有给定日期和月份的所有数据库条目?我试过这个:
scope :with_year_and_month, ->(year, month) {
where("YEAR(created_at) = ? AND MONTH(created_at) = ?", month, year)
}
Run Code Online (Sandbox Code Playgroud)
现在,这在MySQL数据库中可以正常工作,但在Sqlite数据库中它会失败,因为Sqlite没有实现MONTH()和YEAR()函数.以下在Sqlite中工作正常:
scope :with_year_and_month, ->(year, month) {
where("strftime('%m', created_at) = ? AND strftime('%Y', created_at) = ?", "%02d" % month, year.to_s)
}
Run Code Online (Sandbox Code Playgroud)
我将如何以数据库不可知的方式执行此操作?
我认为你应该让活动记录处理这个,因为它检查它正在使用什么数据库并为每个数据库使用驱动程序,诀窍是找到一个通用查询来运行,对我来说这是我能想到的,可能不是最好的,但我愿意接受建议
scope :with_year_and_month, ->(year, month) {
where(created_at: Date.new(year,month,1)..Date.new(year,month,-1))
}
Run Code Online (Sandbox Code Playgroud)
这将生成一个查询之间
WHERE created_at BETWEEN '2015-02-01' AND '2015-02-28'
Run Code Online (Sandbox Code Playgroud)
我认为这应该适合你
如果created_at是DateTime,那么你应该更换Date使用DateTime对象,所以你不要错过之间的时间2015-02-28 00:00:00和2015-02-28 23:59:59,但你需要额外的参数的时间
scope :with_year_and_month, ->(year, month) {
where(created_at: DateTime.new(year,month,1)..DateTime.new(year,month,-1, -1, -1, -1))
}
Run Code Online (Sandbox Code Playgroud)
当然,您可以创建一个小帮助函数来返回这些日期并缩短您的方法.
结果将是
Where created_at BETWEEN '2015-02-01 00:00:00' AND '2015-02-28 23:59:59'
Run Code Online (Sandbox Code Playgroud)
更新:
所以经过几次评论后,这是最终版本
scope :with_year_and_month, ->(year, month) {
date = DateTime.new(year,month)
where(created_at: date...date.next_month)
}
Run Code Online (Sandbox Code Playgroud)
生成的查询将如下所示
created_at >= '2015-02-01 00:00:00' AND created_at < '2015-03-01 00:00:00'
Run Code Online (Sandbox Code Playgroud)