[英]How do you iterate over a range of numbers with each do with/ ERB Ruby on Rails 6?
[英]Ruby/Rails how to iterate months over a DateTime range?
我正在尝试从Rails表中的数据构建图形:每个时间段的已售产品数量。
因为该图应该能够显示最后一小时(以1分钟为单位),最后一天(以1小时为单位),最后一周(以1天为单位),最后一个月(以1天为单位) )等,我正在尝试通过遍历一系列DateTime对象来减少代码重复:
# To prevent code-duplication, iterate over different time ranges.
times = {
:hour=>{newer_than: 1.hour.ago, timestep: :minute},
:day=>{newer_than: 1.day.ago, timestep: :hour},
:week=>{newer_than: 1.week.ago, , timestep: :day},
:month=>{newer_than: 1.week.ago, , timestep: :day}
}
products = Product.all
# Create symbols `:beginning_of_minute`, `:beginning_of_hour`, etc. These are used to group products and timestamps by.
times.each do|name, t|
t[:beginning_of] = ("beginning_of_" << t[:timestep].to_s).to_sym
end
graphs = times.map do |name, t|
graphpoints = {}
seconds_in_a_day = 1.day.to_f
step_ratio = 1.send(t[:timestep]).ago.to_f / seconds_in_a_day
time_enum = 1.send(t[:timestep]).ago.to_datetime.step(DateTime.now, step_ratio)
time_enum.each do |timestep|
graphpoints[time_moment.send(timehash[:beginning_of]).to_datetime] = []
end
# Load all products that are visible in this graph size
visible_products = products.select {|p| p.created_at >= t.newer_than}
# Group them per graph point
grouped_products = visible_products.group_by {|item| item.created_at.send(timehash[:beginning_of]).to_datetime}
graphpoints.merge!(grouped_products)
{
points: graphpoints,
labels: graphpoints.keys
}
end
此代码适用于大小固定(小时,天,周)的所有时间间隔。 但是,对于几个月,它使用30天的1.month / 1.day == 30
: 1.month / 1.day == 30
。 显然,几个月的天数不是恒定的。 在我的脚本中,这导致一个月可能被“跳过”,因此从图中丢失。
如何解决这个问题? 如何在几个月中进行迭代,同时牢记几个月中不同的天数?
使用groupdate gem。 例如(来自文档的修改示例):
visible_products = Product.where("created_at > ?", 1.week.ago).group_by_day
# {
# 2015-07-29 00:00:00 UTC => 50,
# 2013-07-30 00:00:00 UTC => 100,
# 2013-08-02 00:00:00 UTC => 34
# }
而且,这将更快,因为您的分组/计数将由数据库本身完成,而无需通过Product.all
调用将所有记录传递给您的Rails代码,并且无需为每个对象创建ActiveRecord对象(甚至无关紧要)。
如果必须在一个巨大的数组中选择月份,则只需在两个Date:class之间进行选择即可。
(1.year.ago.to_date..DateTime.now.to_date)).select{|date| date.day==1}.each do |date|
p date
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.