Ruby on rails 从Rails数据库中选择具有特定年份和月份的条目

Ruby on rails 从Rails数据库中选择具有特定年份和月份的条目,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,如何选择datetime中具有给定日期和月份的所有数据库条目?我试过这个: scope :with_year_and_month, ->(year, month) { where("YEAR(created_at) = ? AND MONTH(created_at) = ?", month, year) } 现在,这在MySQL数据库中工作得很好,但在Sqlite数据库中它失败了,因为Sqlite没有实现MONTH()和YEAR()函数。尽管在Sqlite中,以下功能仍然可以正常工作

如何选择datetime中具有给定日期和月份的所有数据库条目?我试过这个:

scope :with_year_and_month, ->(year, month) {
  where("YEAR(created_at) = ? AND MONTH(created_at) = ?", month, year)
}
现在,这在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)
}

我该如何以不依赖数据库的方式来处理这个问题?

我认为应该让active record来处理这个问题,因为它会检查它使用的数据库,并为每个数据库使用一个驱动程序,诀窍是找到一个通用查询来运行,对我来说,这是我能想到的,可能不是最好的,但我愿意听取建议

scope :with_year_and_month, ->(year, month) {
  where(created_at: Date.new(year,month,1)..Date.new(year,month,-1))
}
这将生成一个中间查询

WHERE created_at BETWEEN '2015-02-01' AND '2015-02-28'
我想这应该适合你

如果创建时间为
DateTime
,则应将
DateTime
对象替换为
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))
}
当然,您可以创建一个小助手函数来返回这些日期并缩短您的方法。
结果将是

Where created_at BETWEEN '2015-02-01 00:00:00' AND '2015-02-28 23:59:59'
更新:

经过几句评论,这里是最终版本

scope :with_year_and_month, ->(year, month) {
  date = DateTime.new(year,month)
  where(created_at: date...date.next_month)
}
生成的查询如下所示

created_at >= '2015-02-01 00:00:00' AND created_at < '2015-03-01 00:00:00'
创建时间>='2015-02-01 00:00:00'和创建时间>'2015-03-01 00:00:00'

实际上我没有考虑过这样做。我稍微修改了代码,使其更加健壮:
d=DateTime.new(year,month);其中(创建于:d..d.下个月)
。这样的话,这个月的最后一部分就不可能被排除在外了。是的,这是可行的,但请记住,这将包括第一天的开始,这在我的例子中是
2015-03-01 00:00:00
,我知道这是一个非常罕见的情况,但请记住。好的观点。使用
而不是
应该可以解决这个问题(通过将范围的末尾设置为独占)。显然还有
月底
,这也很好,我将把它添加到回答中使用
月底
的问题是,它会排除在该月最后一秒创建的任何内容,因为
DATETIME
以毫秒精度存储在数据库中。这就是为什么我不到下个月初就去了。