Reputation: 16177
According to the Rails guides, this is how would you query with ranges:
http://edgeguides.rubyonrails.org/active_record_postgresql.html#range-types
## All Events on a given date
Event.where("dates @> ?::date", Date.new(2014, 2, 12))
But how do I get all the events within a daterange?
I know I can do this:
Event.where("dates && daterange(?, ?)", date1, date2)
But this daterange will default to use '[)' as the bounds. Is there a way to supply a range, instead of two dates, so that the actual bounds are taken in consideration automatically?
Notice that these are different:
date1..date2 != date1...date2
So far I am doing this:
if dates.exclude_end?
Event.where("dates && daterange(?, ?, '[)')", dates.begin, dates.end)
else
Event.where("dates && daterange(?, ?, '[]')", dates.begin, dates.end)
end
But is there a better way? I would love something as this:
Event.where("dates && ?::daterange)", dates)
EDIT:
In my case, the dates
is a daterange.
[6] pry(main)> Reservation.where(dates: Date.current..4.days.from_now.to_date).explain
Reservation Load (0.8ms) SELECT "reservations".* FROM "reservations" WHERE ("reservations"."dates" BETWEEN $1 AND $2) [["dates", Mon, 30 Jan 2017], ["dates", Fri, 03 Feb 2017]]
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: malformed range literal: "2017-01-30"
Upvotes: 1
Views: 1071
Reputation: 36214
Your if
logic seems solid. Maybe you could simplify it more, like
Event.where("dates && daterange(?, ?, ?)",
dates.begin, dates.end, dates.exclude_end? ? '[)' : '[]')
This way, all your variables are bound parameters & don't have to use 2 distinct queries.
daterange
is a PostgreSQL specific type and as such, it is not very well supported in ORMs. (Also, it seems that ActiveRecord binds ranges as BETWEEN
expressions, so you can't bind them as values).
Upvotes: 1