Rails gem Ransack -> search 'or condition' with 'is null' and a specific value (field=x OR field IS NULL)

此生再无相见时 提交于 2019-12-06 02:37:20

I also had to figure this out and @TomG answer helped a lot! You really don't need to create a ransacker for this issue, it an be fixed by using the build_grouping method of ransack (that is not documented anywhere...) and put in the condition you need with 'or' condition.

I used it to search items to add to a cage but wanted to show the user only items that are not already in my cage (and also not assigned to any other cage), so in my controller:

   @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?

So when I'm printing the query ransack is running it will show:

 @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))"

and if I add a name query:

@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)))"

Hope this helps you or someone else with having trouble using OR in ransack conditions instead of the basic AND.

OK - here is my own solution - inspired by graywh (thank you very much): ransack/issues/290

You can add a new grouping node -with an 'or'-combinator- to the ransack object.

In index view I changed f.select :user_id_eq to 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

You could build your query params like this

q: {g: [ {m: 'or', user_id_eq: 5, user_id_null: 1} ] }

where this:

user_id_null: 1

is only flag to search for null value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!