Rails & Ransack — сортировка/поиск на основе определения в модели

Скажем, например, у меня есть событие с start_date и length (как целое число, представляющее дни).

В модели я определяю end_date как start_date + length.days очень просто, как и следовало ожидать:

def end_date
  start_date + length.days
end

В шаблоне все работает нормально, я могу использовать event.end_date для отображения даты начала плюс сколько дней было установлено, однако, теперь я хочу упорядочить события по дате окончания с помощью Ransack.

Ссылка сортировки для start_date выглядит так: <%= sort_link @q, :start_date, "Start" %>

Если я попытаюсь сделать то же самое для end_date (<%= sort_link @q, :end_date, "End" %>), это, к сожалению, тихо завершится ошибкой, поскольку я предполагаю, что он ищет end_date как столбец в таблице и не находит его.

Я просто веду себя глупо или пытаюсь сделать что-то, для чего Ранзак просто не был создан?


person bensmithbwd    schedule 07.03.2013    source источник
comment
похоже, что ransack переводит параметры поиска в запросы к ORM ActiveRecord, что определенно не удастся, если у вас нет реального столбца, по которому базовая БД может выполнять поиск.   -  person    schedule 07.03.2013
comment
Спасибо за комментарий @bdares. Теперь мне удалось установить ransacker :end do |r| в модели следующим образом: Arel::Nodes::SqlLiteral.new("DATE_ADD(events.start_date, INTERVAL events.length DAY)"). Что производит запрос: SELECT DISTINCT events.* FROM events ORDER BY DATE_ADD(events.start_date, INTERVAL events.length DAY) DESC LIMIT 30 OFFSET 0. Это работает, но кажется ужасно «хакерским».   -  person bensmithbwd    schedule 07.03.2013
comment
@bensmithbwd - в вашем комментарии сложно увидеть полное решение. Не забудьте написать полный пример, чтобы мы могли лучше понять решение. Тогда вы можете принять свой собственный ответ.   -  person Javid Jamae    schedule 13.03.2013
comment
@JavidJamae Я опубликовал ответ, который должен сделать его немного яснее   -  person bensmithbwd    schedule 15.03.2013


Ответы (1)


Просто для тех, кто хочет увидеть, как я это сделал:

В модели, где я определил end_date

def end_date
  start_date + length.days
end

Затем я добавил метод ранжирования для :end_date.

ransacker :end_date do |r|
   Arel::Nodes::SqlLiteral.new("DATE_ADD(`events`.`start_date`, INTERVAL `events`.`length` DAY)")
end

Честно говоря, я не знаю, лучший/правильный ли это способ сделать вышеприведенное предложение, но я гораздо лучше знаком с SQL, чем с Ruby/Rails, так что это сработало для меня, будучи настолько открытым.

Что это эффективно делает, так это создает часть SQL, которая упорядочивает запрос по тому же определению, что и end_date (start_date + длина)

Теперь я могу использовать в шаблоне следующий код для ссылки сортировки (что позволяет Ransacker обрабатывать ASC/DESC и не мешать wil_paginate и т. д. и т. д.):

<%= sort_link @q, :end_date, "Event End Date" %>

Когда вы нажмете на эту ссылку, вы получите запрос следующего содержания:

SELECT DISTINCT events.* FROM events ORDER BY DATE_ADD(events.start_date, INTERVAL events.length DAY) DESC LIMIT 30 OFFSET 0 - Все создано и обработано Ransacker в столбце вашей таблицы, которого даже не существует!

Опять же, быстрый отказ от ответственности, я изучаю Rails и Ruby уже около 2 недель, исходя из фона PHP, поэтому я НИ В КОЕМ СЛУЧАЕ не являюсь экспертом, и это может быть ужасно неэффективно, или может быть гораздо лучший «рельсовый путь». ', о которых я просто не знаю.

person bensmithbwd    schedule 15.03.2013