I have a requirement in ruby where I want to fetch all the data present in database for the current month. However, there is a catch. I wanted to fetch the data of current month based on plan start data.
Ex:
1. My plan is started on 5th Oct 2022.
2. Let say, today's date is 3rd Dec 2022. I would want to fetch records from 5th Nov to 3rd Dec.
3. Let say, today's date is 15th Dec 2022. I would like to fetch records of current cycle that is from 5th Dec till today.
There could be many cases, but the idea is I want to fetch the current month records based on the cycle start date for current month.
Since I am new to ruby, can someone please suggest me how to do it using DateTime or any relevant methods. Any help would be appreciated.
model:
class Customer
include Mongoid::Document
include Mongoid::Timestamps
include SimpleEnum::Mongoid
field :topic, type: String # This field is to store title/topic
field :external_uuid, type: String # This represents unique ID
field :start_time, type: DateTime
field :duration, type: Integer
field :created_at, type: DateTime
field :random, type: Float, default: -> { rand.round(8) }
as_enum :type,
internal: 'internal',
external: 'external'
end
CodePudding user response:
Based on my understanding that the plan starts on each 5th and you want to have the time-span from plan_start
to NOW
, you can get the start date with something along the lines of
require 'date'
plan_start_day = 5
today = DateTime.now.to_date
puts "Today is #{today}"
puts "Today is day #{today.day} of the month, plan starts on #{plan_start_day}."
start =
if today.day < plan_start_day
DateTime.new(today.year,today.month - 1,plan_start_day)
else
DateTime.new(today.year,today.month,plan_start_day)
end
puts "Applicable plan start is #{start.to_date}"
For today we get an output like
Today is 2022-12-13
Today is day 13 of the month, plan starts on 5.
Applicable plan start is 2022-12-05
Now, assuming that the date you are looking for is in start_time
column, that is of type DateTime
, you can just query:
Customer.where('start_time > ? AND start_time < ?', start, today.end_of_day)
Of course created_at
would also work, given that this column provides the information needed... Availability of end_of_day
depends on Rails version but a manual increase as above should be easy enough...
If you want to have the number of items only use
Customer.where('start_time > ? AND start_time < ?', start, today.end_of_day).count
Now, I'd add this to the Customer
model class as a static method
def self.monthly_sum(date)
month = (date.day < Customer::PLAN_START_DAY) : date.month - 1 ? date.month
plan_start = DateTime.new(date.year, month, Customer::PLAN_START_DAY)
plan_end = DateTime.new(date.year, month 1, Customer::PLAN_START_DAY)
Customer.where('start_time > ? AND start_time < ?', plan_start, plan_end).count
end
This method uses the assumption that there are no "future" events, thus it would fetch the full month for any date. If the plan_month has already ended, it will get the full data. If it is the current plan_month, we get all data until today (as no newer entries exist).
The Customer::PLAN_START_DAY
here is a constant.
If the plan start is individual (per user, type, project, ...), you need to get it from the appropriate record and extract the day with the #day
method presented above.
you can now do
Customer.monthly_sum(DateTime.now)
or what ever date is applicable and get the number of records matched.