Mut*_*tor 66 activerecord ruby-on-rails ruby-on-rails-3 rails-activerecord
我有一个具有日期属性的ActiveRecord模型.是否可以使用该日期属性按年,日和月查找:
Model.find_by_year(2012)
Model.find_by_month(12)
Model.find_by_day(1)
Run Code Online (Sandbox Code Playgroud)
或者只是可以find_by_date(2012-12-1).
我希望我可以避免创建年,月和日属性.
mu *_*ort 162
假设你的"日期属性"是一个日期(而不是一个完整的时间戳),那么一个简单的where将给你"按日期查找":
Model.where(:date_column => date)
Run Code Online (Sandbox Code Playgroud)
你不希望find_by_date_column因为这最多会给出一个结果.
对于年,月和日查询,您需要使用extractSQL函数:
Model.where('extract(year from date_column) = ?', desired_year)
Model.where('extract(month from date_column) = ?', desired_month)
Model.where('extract(day from date_column) = ?', desired_day_of_month)
Run Code Online (Sandbox Code Playgroud)
但是,如果你使用的是SQLite,你必须要搞乱,strftime因为它不知道是什么extract:
Model.where("cast(strftime('%Y', date_column) as int) = ?", desired_year)
Model.where("cast(strftime('%m', date_column) as int) = ?", desired_month)
Model.where("cast(strftime('%d', date_column) as int) = ?", desired_day_of_month)
Run Code Online (Sandbox Code Playgroud)
在%m与%d格式说明会在某些情况下,添加前导零,并能迷惑平等的测试,因此cast(... as int)迫使格式化字符串的数字.
ActiveRecord不会保护您免受数据库之间的所有差异的影响,因此只要您执行任何不重要的操作,您就必须构建自己的可移植层(丑陋但有时必要),将自己绑定到一组有限的数据库(除非是现实的,否则你正在发布必须在任何数据库上运行的东西),或者在Ruby中做你所有的逻辑(对任何非常重要的数据都是疯狂的).
大型桌子上的年,月和日查询速度相当慢.有些数据库允许你在函数结果上添加索引,但是ActiveRecord太愚蠢而无法理解它们,所以如果你试图使用它们会很麻烦; 所以,如果你发现这些查询太慢,那么你将不得不添加你想要避免的三个额外列.
如果你要经常使用这些查询,那么你可以为它们添加范围,但是添加带参数的范围的推荐方法就是添加一个类方法:
使用类方法是接受范围参数的首选方法.这些方法仍然可以在关联对象上访问...
所以你的类方法看起来像这样:
def self.by_year(year)
where('extract(year from date_column) = ?', year)
end
# etc.
Run Code Online (Sandbox Code Playgroud)
BSB*_*BSB 29
数据库独立版......
def self.by_year(year)
dt = DateTime.new(year)
boy = dt.beginning_of_year
eoy = dt.end_of_year
where("published_at >= ? and published_at <= ?", boy, eoy)
end
Run Code Online (Sandbox Code Playgroud)
Bee*_*tty 11
对于MySQL试试这个
Model.where("MONTH(date_column) = 12")
Model.where("YEAR(date_column) = 2012")
Model.where("DAY(date_column) = 24")
Run Code Online (Sandbox Code Playgroud)
张健健*_*张健健 10
在您的模型中:
scope :by_year, lambda { |year| where('extract(year from created_at) = ?', year) }
Run Code Online (Sandbox Code Playgroud)
在您的控制器中:
@courses = Course.by_year(params[:year])
Run Code Online (Sandbox Code Playgroud)
小智 6
要查找与特定日期/月份/年份匹配的所有记录,您可以执行以下操作:
Model.where(date: Date.today.all_day)
Model.where(date: Date.today.all_month)
Model.where(date: Date.today.all_year)
Run Code Online (Sandbox Code Playgroud)
.all_X返回日期范围:
Time.current.all_year
=> Sat, 01 Jan 2022 00:00:00.000000000 UTC +00:00..Sat, 31 Dec 2022 23:59:59.999999999 UTC +00:00
Run Code Online (Sandbox Code Playgroud)
我认为最简单的方法是范围:
scope :date, lambda {|date| where('date_field > ? AND date_field < ?', DateTime.parse(date).beginning_of_day, DateTime.parse(date).end_of_day}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
Model.date('2012-12-1').all
Run Code Online (Sandbox Code Playgroud)
这将返回所有模型,其中date_field位于您发送日期的开始和结束之间.
app/models/your_model.rb
scope :created_in, ->( year ) { where( "YEAR( created_at ) = ?", year ) }
Run Code Online (Sandbox Code Playgroud)
Usage
Model.created_in( 1984 )
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
52654 次 |
| 最近记录: |