Usando funções SQL no Active Record
A maioria dos bancos de dados SQL oferece funções para extrair partes de uma data. Por exemplo, o PostgreSQL usa EXTRACT(DOW FROM date), onde DOW significa “day of the week” (dia da semana), retornando valores de 0 (domingo) a 6 (sábado).
Vamos considerar um model Task com uma coluna created_at. Nosso objetivo é buscar registros criados apenas em dias úteis. Vamos usar os recursos de consulta do Active Record para isso.
# app/models/task.rb
class Task < ApplicationRecord
scope :weekdays_only, -> { where("EXTRACT(DOW FROM created_at) BETWEEN 1 AND 5") }
end
Explicação:
-
EXTRACT(DOW FROM created_at): extrai o dia da semana do timestampcreated_at. -
BETWEEN 1 AND 5: limita a seleção de segunda a sexta-feira.
Usando os métodos de Date do Ruby com o Active Record
Se você quiser usar estritamente os métodos de Date do Ruby, pode modificar o código para filtrar os registros depois de buscá-los no banco de dados, mas isso não é eficiente para conjuntos de dados maiores.
# app/models/task.rb
class Task < ApplicationRecord
def self.weekdays_only_ruby
all.select { |task| task.created_at.on_weekday? }
end
end
Explicação:
- Este método primeiro busca todos os registros do banco de dados e depois os filtra usando o método
on_weekday?do Ruby. -
task.created_at.on_weekday?: converte o timestamp created_at em um objeto Date do Ruby e verifica se é um dia útil (de segunda a sexta-feira).
Exemplo de uso:
Task.weekdays_only_ruby
Observação: esta abordagem pode ser ineficiente porque busca primeiro todos os registros do banco de dados e depois os processa em memória. Ela é recomendada para conjuntos de dados pequenos. Se você estiver trabalhando com conjuntos de dados maiores, a solução em SQL será muito mais eficiente.
Combinando condições com o Active Record
Talvez você queira filtrar registros por dias úteis e por uma condição específica, como um status. Isso é possível encadeando scopes:
# 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
Exemplo de uso:
Task.weekdays_only.completed
Consultas em diferentes fusos horários
Ao lidar com fusos horários, garanta que os timestamps created_at sejam convertidos corretamente. Use a cláusula AT TIME ZONE do SQL para comparações precisas.
# 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
Exemplo de uso:
Task.weekdays_only_in_timezone('UTC')
Lidando com outros bancos de dados
Bancos de dados SQL diferentes podem usar funções diferentes para extrair datas:
- MySQL:
DAYOFWEEK(created_at) - SQLite:
strftime('%w', created_at)
Ajuste suas consultas de acordo com o banco de dados utilizado:
# Example for MySQL
scope :weekdays_only, -> { where("DAYOFWEEK(created_at) BETWEEN 2 AND 6") }
Depois de implementar esses scopes, consultar Task.weekdays_only resultará em uma coleção de tarefas criadas apenas em dias úteis. Veja um exemplo:
tasks = Task.weekdays_only
tasks.each do |task|
puts task.created_at
end
Saída:
2024-08-26 10:30:00 UTC # Monday
2024-08-27 11:45:00 UTC # Tuesday
2024-08-28 09:00:00 UTC # Wednesday
Conclusão
Filtrar resultados do Active Record para incluir apenas dias úteis é simples quando você aproveita funções SQL e métodos Ruby para extrair partes de uma data.
Outros artigos que você pode gostar:
- Como extrair o total de dias, horas ou minutos no PostgreSQL
- Como criar gráficos usando Ruby on Rails
Beekeeper Studio é um cliente de banco de dados gratuito e open source
A melhor ferramenta de consultas e edição de SQL que já usei. Tem tudo o que preciso para gerenciar meu banco de dados. - ⭐⭐⭐⭐⭐ Mit
O Beekeeper Studio é rápido, intuitivo e fácil de usar. Ele suporta vários bancos de dados e funciona muito bem no Windows, Mac e Linux.
O que os usuários dizem sobre o Beekeeper Studio
"O Beekeeper Studio substituiu completamente meu antigo fluxo de trabalho com SQL. É rápido, intuitivo e torna o trabalho com banco de dados agradável de novo."
"Já testei muitas GUIs de banco de dados, mas o Beekeeper encontra o equilíbrio perfeito entre recursos e simplicidade. Simplesmente funciona."