Understand Scope Returns Discussion
Excellent episode Collin!
Another tip is you could keep the future_events
scope returning a Relation. And possibly break the sorting out in case it’s used for other queries as your application grows.
class Event < ApplicationRecord
scope :future_events, -> { where("start_time > ?", Time.current) }
scope :newest_first, -> { order(start_time: :asc) }
def self.first_future_event
future_events.newest_first.first
end
end
Elaborating further on this theme of composable scopes, and being handy both for tests and for reporting, leaning on the predicate builder and a default parameter:
scope :future, ->(after = Time.current) { where.not(start_time: ..after) }
There’s also an argument for using a CurrentAttributes value for time, since application code depending directly on Time.current may fall into the trap of assuming it is the same value throughout a single request’s execution, when of course it may not be, leading to some really subtle intermittent bugs, especially at the cusp of midnight.
Very interesting episode, Collin! TIL you could get the path to the source of a method right from the console ✨