Rails gem Ransack -> search 'or condition' с 'is null' и определенным значением (field=x OR field IS NULL)
Я сделал систему поддержки для наших сторонников - запрограммирован на ruby на рельсах (Ruby 1.9.3 Rails 3.2)
Есть модель билета с belongs_to
ассоциация с пользователями (сторонник).
Я использую драгоценный камень Эрни Рэнсак для поиска. Когда сторонник ищет свои собственные билеты (обработанные tickets_controller.index), он также должен увидеть несвязанные билеты в результате поиска (views/tickets/index) (в сочетании с другими условиями поиска, например, "дата" или что-то еще)
(Так что он может взять открытый билет)
ожидаемый оператор SQL:
SELECT * FROM tickets WHERE ... AND (user_id=5 OR user_id IS NULL) AND ...
Я старался user_id_null_or_user_id_eq
в поисковой форме представления индекса - но это не работает (нет ошибки метода)
Как я могу создать собственный предикат (или вымогатель), чтобы решить эту проблему? (Спасибо @Magnuss за этот комментарий)
К сожалению, у меня нет опыта работы с Арелем
Что-то вроде:
ransacker :user_null_or_eq do
...
end
в модели билетов.
Я надеюсь, что это объясняет проблему более подробно.
Спасибо за любую помощь.
3 ответа
Я также должен был понять это, и ответ @TomG очень помог! Вам действительно не нужно создавать Ransacker для этой проблемы, это можно исправить с помощью метода build_grouping Ransack (который нигде не документирован...) и поместите в необходимое вам условие с условием 'или'.
Я использовал его для поиска предметов для добавления в клетку, но хотел показать пользователю только те элементы, которых еще нет в моей клетке (а также не назначены ни одной другой клетке), поэтому в моем контроллере:
@search = Cage.ransack(params[:q])
@search.build_grouping({:m => 'or', :storage_id_not_eq => @cage_item.id, :storage_id_null => true})
@results_count = @search.result(:distinct => true).length
@items = @search.result(:distinct => true).paginate(:per_page => 20, :page => params[:page] || 1)
@search.build_condition if @search.conditions.empty?
@search.build_sort if @search.sorts.empty?
Поэтому, когда я печатаю запрос, Ransack работает, он покажет:
@search.result.to_sql
"SELECT `specimens`.* FROM `specimens` WHERE (`specimens`.`deleted_at` IS NULL) AND ((`specimens`.`storage_id` != 183 OR `specimens`.`storage_id` IS NULL))"
и если я добавлю запрос имени:
@search.result.to_sql
"SELECT `specimens`.* FROM `specimens` WHERE (`specimens`.`deleted_at` IS NULL) AND ((`specimens`.`name` LIKE '%root%' AND (`specimens`.`storage_id` != 183 OR `specimens`.`storage_id` IS NULL)))"
Надеюсь, что это поможет вам или кому-то еще с проблемами при использовании ИЛИ в условиях ранчо вместо базового И.
Вы могли бы создать параметры вашего запроса, как это
q: {g: [ {m: 'or', user_id_eq: 5, user_id_null: 1} ] }
где это:
user_id_null: 1
только флаг для поиска нулевого значения
Хорошо - вот мое собственное решение - вдохновлено Graywh (большое спасибо): ransack / Issues / 290
Вы можете добавить новый группирующий узел - с помощью 'или'- комбинатора - к объекту рансинга.
В индексном представлении я изменился f.select :user_id_eq
в select_tag ...
tickets_controller.index:
@q = Ticket.search(params[:q])
if params[:user_id_eq] && params[:user_id_eq]!=''
@q.build_grouping({:m => 'or', :user_id_eq => params[:user_id_eq], :user_id_null => true})
end