Reputation: 1009
You have a model Store
with an attribute time_zone
(New York, London, Tokyo, etc.).
All stores are open from 8am to 9pm in their local time zone.
You have an instance method to check if the store is currently open:
def currently_open?
current_store_time = Time.now.in_time_zone(time_zone)
(8...21).cover? current_store_time.hour
end
How do you create a rails scope for all currently open stores using the Store#currently_open?
instance method (or without that method, but I want to use the rails scope
syntax).
scope :currently_open, -> { "use Store#currently_open? here" }
Upvotes: 0
Views: 707
Reputation: 2032
Does this works for you?
scope :with_current_store_time, -> {
select(all.arel.projections, "date_part('hour', NOW() at time zone time_zone) as current_store_time")
}
scope :currently_open, -> {
with_current_store_time.where(current_store_time: 8..21)
}
Basically I rewrote current_store_time
as a scope (with_current_store_time
)
I answered this using these as references:
How to return current date in a different timezone in PostgreSQL
https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
Rails - Active Record: add extra select column to find(:all)
Notes :
current_store_time
probably not describing the actual value being calculated.
current_store_time
is returning hour, on the specified timezone.
Upvotes: 3
Reputation: 114138
If your table only contains a time_zone
string which contains a valid Rails time zone name (or alias), you'll have to somehow generate a list of time zone names that are currently between 8 am and 9 pm.
To do so, you could write a helper method that fetches the used time zones in your table via Store.distinct.pluck(:time_zone)
and selects those that match the criteria:
class Store
def self.time_zones_between(hours)
distinct.pluck(:time_zone).select do |time_zone|
Time.use_zone(time_zone) { hours.cover?(Time.current.hour) }
end
end
scope :currently_open, -> { where(time_zone: time_zones_between(8...21) }
end
Note that calling Store.currently_open
will result two queries: one to get the time zones and one to fetch the actual results. You can avoid the first query by providing the list of available time zones yourself.
Upvotes: 1