groupdateで一定の期間毎にリソースを集計する

はじめに

どのようなアプリでも、一定の期間で何かしらのイベントを走らせる、といったことは日常的に行われているものと思います。当然、その期間中のリソースの変化を集計したい、といった要望は多いことでしょう。そうした時に便利なのが、groupdateというgemでございます。

実装

groupdateをインストールします。

gem install groupdate

groupdateは所定のタイムゾーンに基づいて、日時のデータを扱います。そこで利用するタイムゾーンを確認する必要がございます。Railsでは以下のコマンドでタイムゾーンの一覧を取得することができます。

bundle exec rake time:zones:all

つらつらと一覧が出てくるので、その中から要件にあったタイムゾーンを確認の上、groupdateのオプションに与えます。下の例では東京を指定しております。ちなみに東京の場合はTokyoとなります。

irb(main):001:0> Groupdate.time_zone = "Tokyo"
=> "Tokyo"

また、mysqlを利用している場合は、mysqlにタイムゾーンのテーブルを別途ロードする必要があります。

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

groupdateをインストールすると、以下のメソッドが利用可能となります。

  • group_by_*
      • second
      • minute
      • hour
      • day
      • week
      • month
      • quarter
      • year
      • hour_of_day
      • day_of_week
      • day_of_month
      • month_of_year

機能は読んで字の如く、対象のリソースに対して、引数に渡したattributeを参照することで、それぞれメソッド名の期間に応じた集計処理を行います。

irb(main):02:0> Post.group_by_week(:created_at).count
(1.4ms) SELECT COUNT(*) AS count_all, CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(created_at, INTERVAL ((1 + WEEKDAY(CONVERT_TZ(created_at, '+00:00', 'Asia/Tokyo') - INTERVAL 0 second)) % 7) DAY) - INTERVAL 0 second, '+00:00', 'Asia/Tokyo'), '%Y-%m-%d 00:00:00') + INTERVAL 0 second, 'Asia/Tokyo', '+00:00') AS convert_tz_date_format_convert_tz_date_sub_created_at_interval_1_weekday_convert_tz_created_at_00_00_asia_tokyo_interval_0_second_7_day_interval_0_second_00_00_asia_tokyo_y_m_d_00_00_00_interval_0_second_asia_tokyo_00_00 FROM `posts` WHERE (created_at IS NOT NULL) GROUP BY CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(created_at, INTERVAL ((1 + WEEKDAY(CONVERT_TZ(created_at, '+00:00', 'Asia/Tokyo') - INTERVAL 0 second)) % 7) DAY) - INTERVAL 0 second, '+00:00', 'Asia/Tokyo'), '%Y-%m-%d 00:00:00') + INTERVAL 0 second, 'Asia/Tokyo', '+00:00')
=> {Sun, 08 Jul 2018=>1, Sun, 15 Jul 2018=>0, Sun, 22 Jul 2018=>0, Sun, 29 Jul 2018=>3}

一見すると簡単なように見えて、意外とバグが入り込みやすいのが、時間を扱う処理でございます。それでいてテストが大変だったりもします。そういった処理をgemとして利用できるというのは、とても嬉しいことではないかなと存じます。

Ruby/Rails界隈のこうした文化は素晴らしいと思います。

Rails

Posted by poison