Ответ 1
Предполагая, что ваш "атрибут даты" является датой (а не полной меткой времени), тогда простой where
предоставит вам вашу "находку по дате":
Model.where(:date_column => date)
Вы не хотите find_by_date_column
, так как это даст не более одного результата.
Для запросов года, месяца и дня вы хотите использовать функцию extract
SQL:
Model.where('extract(year from date_column) = ?', desired_year)
Model.where('extract(month from date_column) = ?', desired_month)
Model.where('extract(day from date_column) = ?', desired_day_of_month)
Однако, если вы используете SQLite, вам нужно будет возиться с strftime
, поскольку он не знает, что такое extract
:
Model.where("cast(strftime('%Y', date_column) as int) = ?", desired_year)
Model.where("cast(strftime('%m', date_column) as int) = ?", desired_month)
Model.where("cast(strftime('%d', date_column) as int) = ?", desired_day_of_month)
Спецификаторы формата %m
и %d
в некоторых случаях будут добавлять ведущие нули и могут путать тесты равенства, поэтому cast(... as int)
принудительно форматирует строки в числах.
ActiveRecord не будет защищать вас от всех различий между базами данных, поэтому, как только вы сделаете что-то нетривиальное, вам либо придется создать свой собственный уровень переносимости (уродливый, но иногда необходимый), привяжите себя к ограниченному набору баз данных (реалистично, если вы не выпускаете что-то, что должно работать в любой базе данных), или выполняйте всю свою логику в Ruby (безумный для любого нетривиального количества данных).
Запросы года, месяца и дня месяца будут довольно медленными на больших таблицах. Некоторые базы данных позволяют добавлять индексы к результатам функций, но ActiveRecord слишком глуп, чтобы понять их, поэтому при попытке их использовать будет большой беспорядок; поэтому, если вы обнаружите, что эти запросы слишком медленные, вам придется добавить три дополнительных столбца, которые вы пытаетесь избежать.
Если вы собираетесь использовать эти запросы много, вы можете добавить области для них, но рекомендуемый способ добавления области с аргументом просто добавить метод класса:
Использование метода класса является предпочтительным способом принятия аргументов для областей. Эти методы все равно будут доступны для объектов ассоциации...
Итак, у вас будут методы класса, которые выглядят так:
def self.by_year(year)
where('extract(year from date_column) = ?', year)
end
# etc.