Where ActiveRecord query return empty AssociationRelation

I want to make a query where results be added to array, example:

app/models/user.rb

query = self.patients.where(["created_at >= ? and created_at >= ? and created_at >= ?", Time.zone.now.beginning_of_day, Time.now.beginning_of_week, Time.now.beginning_of_month]).to_a

Expected result:

query
=> [3, 5, 12]

Current result:

Patient Load (0.8ms)  SELECT `patients`.* FROM `patients` WHERE `patients`.`medic_id` = 1 AND (created_at >= '2018-07-20 00:00:00' and created_at >= '2018-07-16 05:00:00' and created_at >= '2018-07-01 05:00:00')
=> #<ActiveRecord::AssociationRelation []>

without to_a method => [#<ActiveRecord::AssociationRelation []>]
with to_a method => []

Models

class User < ApplicationRecord 
  has_many :patients, dependent: :destroy
end

class Patient < ApplicationRecord
  belongs_to :user
end

I am recieving a empty array/AssociationRelation, how can I get the array with the count of patients for beginning of the day, week, month, like this query = [3, 5, 12]?

Note, using:

  • Mysql: Ver 15.1 Distrib 10.1.34-MariaDB, for Linux (x86_64) using readline 5.1
  • Ruby: 2.3.3p222
  • Rails: 5.0.0.1
  • ActiveRecord: 5.0.0.1

2 answers

  • answered 2018-07-20 17:33 Jay-Ar Polidario

    Solution:

    class Patient < ApplicationRecord
      scope :created_since, -> (time) { where('created_at >= ?', time) }
      # ...
    end
    

    Example:

    how can I get the array with the count of patients for beginning of the day, week, month, like this query = [3, 5, 12]?

    patients_counts = [
      Patient.created_since(Time.zone.now.beginning_of_day).count,
      Patient.created_since(Time.zone.now.beginning_of_week).count,
      Patient.created_since(Time.zone.now.beginning_of_month).count,
    ]
    
    puts patients_counts
    # => [3, 5, 12]
    
    • Just in case you don't know, you can also do it like: @user.patients.created_since(...)

    P.S. I do not suggest doing in one query, and just do three separate count queries like above. You can do it in one query but you'll have to write a very specific SQL, and will get ugly because you'll need three subqueries (from what I can see).

  • answered 2018-07-20 18:08 jedi

    An alternative solution would be to use SQL UNION operator to combine 3 different sets of records filtered by different timestamps. You can read how to achieve such result in this post: ActiveRecord Query Union