繁体   English   中英

使用Ransack搜索值数组

[英]Search an array of values with Ransack

我是Ransack的新手,因此遇到了Ransack没有明确涵盖的情况。 我基本上是想搜索一个值,但搜索到的值包装在一个数组中。

码:

<%= f.search_field :category_or_account_number_or_status_or_account_number_or_account_name_or_accounts_name_or_accounts_number_or_user_name_or_user_rep_code_list_cont_any %>

最后,有一段user_rep_code_list_cont是用户当前的默认数组属性,看起来像这样[[al20“,” b234“]

因此,当我在Ransack搜索栏中键入al20时,出现此错误。

错误:

PG::UndefinedFunction: ERROR:  operator does not exist: character 
varying[] ~~* unknown
LINE 1: ..."name" ILIKE '%al20%') OR "users"."rep_code_list" ILIKE 
'%al...
                                                         ^
HINT:  No operator matches the given name and argument type(s). You 
might need to add explicit type casts.

控制器:

def index
  @q = Submission.submissions_for(user: current_user).ransack(params[:q])
  @submissions = @q.result.includes(:user, :accounts).ordered(current_user).page(params[:page]).per(25)
end

再说一次,我不是Ransack专家,但这似乎是现在应该解决的问题。 我想在作为数组的模型上搜索属性。 任何帮助将非常感谢!

在这种情况下,我最终使用了自定义Ransacker

ransacker :rep_code_list do
  Arel.sql("array_to_string(rep_code_list, ',')")
end

这会将数组转换为字符串,以便Ransack可以使用cont谓词进行搜索。 不知道这是否是最好的方法,但是它适用于我的情况。

使用数组和Ransack并不是那么简单,您必须手动完成许多工作,因为基础查询会迅速将您带入高级领域。 检查数组中的成员资格相对容易 ,根据LIKE模式检查数组中的每个元素会更加复杂,因为您需要对unnest函数调用进行LATERAL JOIN来解开数组,以便可以对它的成员进行LIKE:

select users.*
from users, unnest(users.rep_code_list) c -- This is an implicit LATERAL JOIN
where c ilike '%some-pattern%'

并且您可能想在SELECT子句中distinct on (users.id)一个distinct on (users.id) ,以清除查询其他部分出现的所有重复项:

select distinct on (users.id) users.*
from users, unnest(users.rep_code_list) c -- This is an implicit LATERAL JOIN
where c ilike '%some-pattern%'
  and ...

为了使Ransack使用这样的查询,您需要添加一个范围(并告诉Ransack它可以使用该范围)或编写一个自定义的ransacker 不幸的是,似乎没有任何方法可以让Ransack与通常的attr1_or_attr2_or...参数名称解​​析逻辑一起使用范围,因此您的范围必须全部完成:

class User < ApplicationRecord
  def self.ransackable_scopes(auth = nil)
    %i[things_like]
  end

  def self.things_like(s)
    select('distinct on (users.id) users.*')
      .joins(', unnest(users.rep_code_list) c')
      .where('c ilike :pat or users.category ilike :pat or ...', pat: "%#{s}%")
  end
end

然后以以下形式:

<%= f.search_field :things_like %>

您可能会更好地将LATERAL JOIN逻辑混搭到自定义ransacker中,或者更好的IMO中,用一个单独的表替换该数组,以便可以使用Ransacker的关联逻辑并将代码视为数据库中的一等实体,而不仅仅是字符串。 某种完全测试搜索(而不是Ransack)可能是另一种选择。

您也许可以使用PostgreSQL的array_to_string函数来对数组进行展平,但是您必须处理定界符,并且仍然会遇到“全部完成”作用域(或者可能是自定义ransacker)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM