Usare le funzioni SQL in Active Record
La maggior parte dei database SQL offre funzioni per estrarre parti di una data. Ad esempio, PostgreSQL usa EXTRACT(DOW FROM date), dove DOW sta per “day of the week” (giorno della settimana), e restituisce valori da 0 (domenica) a 6 (sabato).
Prendiamo un modello Task con una colonna created_at. Il nostro obiettivo è recuperare solo i record creati nei giorni feriali. Per farlo useremo le funzionalità di query di Active Record.
# app/models/task.rb
class Task < ApplicationRecord
scope :weekdays_only, -> { where("EXTRACT(DOW FROM created_at) BETWEEN 1 AND 5") }
end
Spiegazione:
-
EXTRACT(DOW FROM created_at): estrae il giorno della settimana dal timestampcreated_at. -
BETWEEN 1 AND 5: limita la selezione da lunedì a venerdì.
Usare i metodi Date di Ruby con Active Record
Se vuoi usare esclusivamente i metodi Date di Ruby, puoi modificare il codice per filtrare i record dopo averli recuperati dal database, ma non è efficiente con dataset di grandi dimensioni.
# app/models/task.rb
class Task < ApplicationRecord
def self.weekdays_only_ruby
all.select { |task| task.created_at.on_weekday? }
end
end
Spiegazione:
- Questo metodo prima recupera tutti i record dal database e poi li filtra con il metodo
on_weekday?di Ruby. -
task.created_at.on_weekday?: converte il timestamp created_at in un oggetto Date di Ruby e verifica se è un giorno feriale (da lunedì a venerdì).
Esempio d'uso:
Task.weekdays_only_ruby
Nota: questo approccio può essere inefficiente perché prima recupera tutti i record dal database e poi li elabora in memoria. È consigliato per dataset piccoli. Se lavori con dataset più grandi, la soluzione SQL sarà molto più efficiente.
Combinare condizioni con Active Record
Potresti voler filtrare i record per giorni feriali e per una condizione specifica, come uno stato. È possibile concatenando gli scope:
# app/models/task.rb
class Task < ApplicationRecord
scope :weekdays_only, -> { where.not("EXTRACT(DOW FROM created_at) IN (0, 6)") }
scope :completed, -> { where(status: 'completed') }
end
Esempio d'uso:
Task.weekdays_only.completed
Query con fusi orari diversi
Quando lavori con i fusi orari, assicurati che i timestamp created_at vengano convertiti correttamente. Usa la clausola AT TIME ZONE in SQL per confronti accurati.
# app/models/task.rb
class Task < ApplicationRecord
scope :weekdays_only_in_timezone, ->(timezone) {
where("EXTRACT(DOW FROM created_at AT TIME ZONE ?) BETWEEN 1 AND 5", timezone)
}
end
Esempio d'uso:
Task.weekdays_only_in_timezone('UTC')
Gestire altri database
Database SQL diversi possono usare funzioni diverse per estrarre parti di una data:
- MySQL:
DAYOFWEEK(created_at) - SQLite:
strftime('%w', created_at)
Assicurati di adattare le tue query in base al database che usi:
# Example for MySQL
scope :weekdays_only, -> { where("DAYOFWEEK(created_at) BETWEEN 2 AND 6") }
Dopo aver implementato questi scope, una query su Task.weekdays_only restituirà una collezione di task creati solo nei giorni feriali. Ecco un esempio:
tasks = Task.weekdays_only
tasks.each do |task|
puts task.created_at
end
Output:
2024-08-26 10:30:00 UTC # Monday
2024-08-27 11:45:00 UTC # Tuesday
2024-08-28 09:00:00 UTC # Wednesday
Conclusione
Filtrare i risultati di Active Record per includere solo i giorni feriali è semplice, sfruttando le funzioni SQL e i metodi Ruby per estrarre parti di una data.
Altri articoli che potrebbero piacerti:
Beekeeper Studio è una GUI per database gratuita & open source
Il miglior strumento per query & editor SQL che abbia mai usato. Offre tutto ciò che mi serve per gestire il mio database. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio è veloce, intuitivo e facile da usare. Beekeeper supporta tantissimi database e funziona alla grande su Windows, Mac e Linux.
Cosa dicono gli utenti di Beekeeper Studio
"Beekeeper Studio ha sostituito completamente il mio vecchio flusso di lavoro SQL. È veloce, intuitivo e rende di nuovo piacevole lavorare con i database."
"Ho provato tante GUI per database, ma Beekeeper trova l'equilibrio perfetto tra funzionalità e semplicità. Funziona e basta."