You can get consecutive quotes via:
Quote.order(:id).offset(0).first
Quote.order(:id).offset(1).first
Quote.order(:id).offset(2).first
# ...
To get a quote for the current day, you can utilize Date#jd
which returns the date's Julian day:
Date.parse('2020-06-01').jd #=> 2459002
Date.parse('2020-06-02').jd #=> 2459003
Date.parse('2020-06-03').jd #=> 2459004
Since you (probably) don't have that many quotes, this value needs to be transformed into a value we can pass to offset
, i.e. a value between 0 and the total number of quotes. This is where the modulo operator %
can help – it returns just that, looping over at the end: (e.g. for 22 quotes)
Date.parse('2020-06-01').jd % 22 #=> 18
Date.parse('2020-06-02').jd % 22 #=> 19
Date.parse('2020-06-03').jd % 22 #=> 20
Date.parse('2020-06-04').jd % 22 #=> 21
Date.parse('2020-06-05').jd % 22 #=> 0
Date.parse('2020-06-06').jd % 22 #=> 1
Putting it all together:
require 'date'
def quote_of_the_day(date = Date.current)
offset = date.jd % Quote.count
Quote.order(:id).offset(offset).first
end
Note that this runs two queries: one to get the total number of quotes and another one to get the quote for the given date. You might want to cache the result.
Also note that adding new quotes might have unexpected results because the modulo operation would return a totally different offset:
Date.parse('2020-06-03').jd % 22 #=> 20
# after adding a new Quote
Date.parse('2020-06-03').jd % 23 #=> 5
You can compensate this by adjusting the jd
result accordingly:
ADJUSTMENT = 15
(Date.parse('2020-06-03').jd + ADJUSTMENT) % 23 #=> 20