2017-01-30 2 views
1

Nach den Rails Guides, das ist, wie würden Sie Bereiche abfragen:Wie kann ich Datumsbereiche in Rails abfragen?

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)) 

Aber wie ich in einem daterange alle Events?

Ich weiß, ich kann dies tun:

Event.where("dates && daterange(?, ?)", date1, date2) 

Aber diese wird standardmäßig daterange verwenden ‚[)‘, wie die Grenzen. Gibt es eine Möglichkeit, anstelle von zwei Daten einen Bereich zu liefern, so dass die tatsächlichen Grenzen automatisch berücksichtigt werden?

Beachten Sie, dass diese unterschiedlich sind:

date1..date2 != date1...date2 

Bisher habe ich dies tue:

if dates.exclude_end? 
    Event.where("dates && daterange(?, ?, '[)')", dates.begin, dates.end) 
else 
    Event.where("dates && daterange(?, ?, '[]')", dates.begin, dates.end) 
end 

Aber gibt es einen besseren Weg?

Event.where("dates && ?::daterange)", dates) 

EDIT:

In meinem Fall die dates ist ein daterange Ich würde etwas wie diese Liebe.

[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" 
+0

Funktioniert etwas wie "Event.where (Datum: Datum1 ... Datum2)" nicht für Ihre Situation? – Iceman

+0

Nein. In meinem Fall ist die Datumsspalte ein Datumsbereich, kein Datum. Siehe https://www.postgresql.org/docs/9.3/static/rangetypes.html – Nerian

+0

Ich habe die Ausgabe für Ihre Abfrage in den Abschnitt 'Bearbeiten' der Antwort eingefügt. – Nerian

Antwort

1

Ihre if Logik scheint solide. Vielleicht könnten Sie es vereinfachen wie

Event.where("dates && daterange(?, ?, ?)", 
      dates.begin, dates.end, dates.exclude_end? ? '[)' : '[]') 

diese Weise alle Variablen Parameter gebunden & müssen nicht zwei unterschiedliche Abfragen verwenden.

daterange ist ein PostgreSQL-spezifischer Typ und wird daher in ORMs nicht sehr gut unterstützt. (Es scheint auch, dass ActiveRecord Bereiche als BETWEEN Ausdrücke bindet, so dass Sie sie nicht als Werte binden können).