Rails gem Ransack - >搜索或条件'用'为空'和一个特定的值(field = x OR field IS NULL)

时间:2013-10-18 10:47:01

标签: ruby-on-rails arel ransack

我为我们的支持者制作了一个支持票系统 - 用ruby on rails编程(Ruby 1.9.3 Rails 3.2)

有一个与用户(支持者)有belongs_to关联的故障单模型。

我使用Ernie的gem Ransack进行搜索。 当支持者搜索他自己的票据(由tickets_controller.index处理)时,他还应该在搜索结果中看到无关联票证(views / tickets / index)(结合其他搜索条件,例如“date”或其他)< / p>

(这样他就可以开门票了)

预期的SQL语句:

SELECT * FROM tickets WHERE ... AND (user_id=5 OR user_id IS NULL) AND ... 

我在索引视图的搜索表单中尝试user_id_null_or_user_id_eq - 但这不起作用(没有方法错误)

如何制作自定义谓词(或ransacker)来解决此问题? (感谢@Magnuss的评论)

不幸的是,我没有Arel的经验

类似的东西:

ransacker :user_null_or_eq do
    ...
end

在门票模型中。

我希望这能更详细地解释这个问题。

感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

我也必须弄明白这一点,@ TomG的答案帮了很多忙! 你真的不需要为这个问题创建一个ransacker,可以通过使用ransack的build_grouping方法(在任何地方都没有记录......)修复它,然后用'或'条件放入你需要的条件。

我用它来搜索要添加到笼子中的项目但是只想向用户显示尚未在我的笼子中的项目(也没有分配给任何其他笼子),所以在我的控制器中:

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

希望这可以帮助您或其他人在搜索条件而不是基本的AND中使用OR时遇到问题。

答案 1 :(得分: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

答案 2 :(得分:1)

您可以像这样构建查询参数

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

这里:

user_id_null: 1

只是搜索空值的标志