Предполагая, что ваш «атрибут даты» является датой (а не полной отметкой времени), тогда простой 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.
person
mu is too short
schedule
08.03.2012