获取相对日期之间的对象大小

时间:2012-03-16 17:16:29

标签: ruby-on-rails ruby mongoid date

我有很多具有created_at属性的用户对象,例如

我使用@users = User.all

获取对象

我希望通过

创建具有不同年龄的User对象的数量
@users.size

这些日期范围:

yesterday
last week
last month
last year.

我该怎么做?

我使用mongoid。

1 个答案:

答案 0 :(得分:2)

您可以为此编写范围:

class User
  include Mongoid::Document
  ...

  ## Scopes for calculating relative users
  scope :created_yesterday, lambda { where(:created_at.gte => (Time.now - 1.day)) }
  scope :created_last_week, lambda { where(:created_at.gte => (Time.now - 1.week)) }
  scope :created_last_month, lambda { where(:created_at.gte => (Time.now - 1.month)) }
  scope :created_last_year, lambda { where(:created_at.gte => (Time.now - 1.year)) }
  ...
end

我们需要在这里使用lambda的原因是它将Time.now参数的评估延迟到实际调用范围的时间。如果没有lambda,查询逻辑中使用的时间将是首次评估类的时间,而不是范围本身。

现在我们可以通过简单地调用来获取计数:

User.created_yesterday.count
User.created_last_week.count
...

如果你想要对象:

@users_created_yesterday = User.created_yesterday

您可以在视图中使用@users_created_yesterday

<强>更新

与昨天一样,如果你的意思是从昨天开始的0:00到昨天结束的23:59之间的时间,你将需要考虑时区。

例如,在你的application.rb中,如果你写了:

# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
 config.time_zone = 'Central Time (US & Canada)'

如果您使用此功能,则activerecord查询提取的所有时间都将转换为此时区(中部时间(美国和加拿大))。在数据库中,所有时间都将以UTC格式存储,并在从数据库中提取时转换为时区。如果您已注释掉此行,则默认为UTC。您可以使用rake任务rake time:zones:all获取所有时区,也可以使用rake time:zones:us仅使用美国时区。

如果您想要application.rb中指定的时区,则需要在以下代码中使用Time.zone.now。如果您在以下代码中使用Time.now,则将根据服务器计算机的时区获取时区。

class User
  include Mongoid::Document
  ...
  scope :created_between, lambda { |start_time, end_time| where(:created_at => (start_time...end_time)) }

  class << self
    ## Class methods for calculating relative users
    def created_yesterday
      yesterday = Time.zone.now - 1.day
      created_between(yesterday.beginning_of_day, yesterday.end_of_day)
    end

    def created_last_week
      start_time = (Time.zone.now - 1.week).beginning_of_day
      end_time = Time.zone.now
      created_between(start_time, end_time)
    end

    def created_last_month
      start_time = (Time.zone.now - 1.month).beginning_of_day
      end_time = Time.zone.now
      created_between(start_time, end_time)
    end

    def created_last_year
      start_time = (Time.zone.now - 1.year).beginning_of_day
      end_time = Time.zone.now
      created_between(start_time, end_time)
    end
  end

  ..
  ..
end

因此,您可以编写类方法并计算开始时间和结束时间,将其提供给范围created_between,您可以像User.created_yesterday一样调用它们,就像我们之前调用的那样。 / p>

致谢: EdgeRails 。由于它是Mongoid,我不得不抬头看Mongoid docs