Получить размер объектов между относительными датами - PullRequest
1 голос
/ 16 марта 2012

У меня есть много объектов User с атрибутом created_at, например.

Я получаю объекты с @users = User.all

Я хочу получить количество пользовательских объектов разного возраста от создания с помощью

@users.size

для этих диапазонов дат:

yesterday
last week
last month
last year.

Как я могу это сделать?

Я использую монгоид.

1 Ответ

2 голосов
/ 16 марта 2012

Вы можете написать области для этого:

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

Причина, по которой нам нужно использовать лямбду, заключается в том, что она задерживает оценку аргумента Time.now до момента фактического вызова области. Без лямбды время, которое будет использоваться в логике запроса, будет временем, когда класс был впервые оценен, а не самой областью действия.

Теперь мы можем получить количество, просто позвонив:

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, как мы вызывали ранее.

Кредиты: EdgeRails . Так как это Mongoid, мне пришлось посмотреть на Mongoid docs

...