[英]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.