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
Другие вопросы по тегам