- 更新日: 2016年1月18日
- Rails
RailsのActiveRecordで今日・昨日など特定の日に保存されたレコードを取得
Rails の ActiveRecord で、今日や昨日、一週間前など特定の1日のうちに保存されたレコードをすべて一括で取得する方法です。
— 環境 —
Rails 4.1.1
Ruby 2.1.2
特定の日に保存されたレコードを取得する scope の例
ユーザーが投稿したポスト(Post モデル)を例に、今日や昨日、1ヶ月前など特定の日に投稿されたポストを取得する scope を以下のように書きます。
app/models/post.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class Post < ActiveRecord::Base # ... # 今日投稿された Post を取得 scope :created_today, -> { where("created_at >= ?", Time.zone.now.beginning_of_day) } # または # scope :created_today, -> { where(created_at: Time.zone.now.all_day) } # 昨日投稿された Post を取得 scope :created_yesterday, -> { where(created_at: 1.day.ago.all_day) } # 3日前に投稿された Post を取得 scope :created_three_days_ago, -> { where(created_at: 3.days.ago.all_day) } # 一週間前に投稿された Post を取得 scope :created_a_week_ago, -> { where(created_at: 1.week.ago.all_day) } # 一ヶ月前に投稿された Post を取得 scope :created_a_month_ago, -> { where(created_at: 1.month.ago.all_day) } # ... end |
上記の scope を使う
Time#all_day は Range オブジェクトを返し、Time#all_day を使った場合は、SQL としては BETWEEN を使った SQL が発行される。Rails コンソールで確認。
1 2 3 4 5 6 7 8 |
$ bundle exec rails c pry(main)> 1.day.ago.all_day => Tue, 12 Jan 2016 00:00:00 UTC +00:00..Tue, 12 Jan 2016 23:59:59 UTC +00:00 pry(main)> Post.created_yesterday Post Load (0.6ms) SELECT `posts`.* FROM `posts` WHERE (`posts`.`created_at` BETWEEN '2016-01-12 00:00:00' AND '2016-01-12 23:59:59') |
pry で確認したところ、BETWEEN の SQL が発行されるのを確認できた。
上記 scope 例を使う場合の注意点
また、上記 scope 例は注意点が一つありまして、Rails の Time.zone で取得されるタイムゾーンでの丸1日分のレコードを取得してきます。Time.zone は config/application.rb の config.time_zone の設定が反映され、デフォルトでは UTC となる。
なので Time.zone が UTC となっている場合は、上記の例では UTC での丸一日分のレコードを取得してきます。ユーザーごとのタイムゾーンでの丸一日分など、例えば日本時間での丸一日分のレコードを取得するには、以下のようにタイムゾーンを考慮したコードが必要になるかと思います。
1 2 3 4 5 6 7 |
pry(main)> Time.now.in_time_zone("Tokyo").beginning_of_day => Wed, 13 Jan 2016 00:00:00 JST +09:00 pry(main)> 1.day.ago.in_time_zone("Tokyo").all_day => Tue, 12 Jan 2016 00:00:00 JST +09:00..Tue, 12 Jan 2016 23:59:59 JST +09:00 |
ユーザーごとの複数タイムゾーンへの対応は、以下記事が大変参考になる。
Working with time zones in Ruby on Rails – Elabs
このページの “Working with multiple user time zones” に書いてある方法が良さそう。コントローラーの around_action で、Time.use_zone を使ってユーザーのタイムゾーンを設定する方法。
Rails で世界中の複数のタイムゾーンに対応する場合、タイムゾーンの扱いは相当ややこしい。これについては、もう少し掘り下げて別途記事を書く予定です。
- – 参考リンク –
- date – How to get record created today by rails activerecord? – Stack Overflow
- Railsで特定の日の新規ユーザ数などを取るクエリを作る – Qiita
- Rails の関連記事
- RailsでMySQLパーティショニングのマイグレーション
- Rails ActiveRecordでdatetime型カラムのGROUP BY集計にタイムゾーンを考慮する
- RailsプラグインGemの作成方法、RSpecテストまで含めたrails pluginの作り方
- RailsでAMPに対応するgemをリリースしました
- Railsでrequest.urlとrequest.original_urlの違い
- Railsでwheneverによるcronバッチ処理
- Google AnalyticsのRails Turbolinks対応
- Railsアプリにソーシャル・シェアボタンを簡単設置
- Rails監視ツール用にErrbitをHerokuで運用
- Facebook APIバージョンのアップグレード手順(Rails OmniAuth)
- 初回公開日: 2016年1月13日
Leave Your Message!