我是Ransack的新手,而且我遇到了一个似乎并未被Ransack彻底覆盖的案例。我基本上试图搜索一个值,但搜索到的值被包装在一个数组中。
data.table
最后有一块<%= 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 %>
是用户的默认数组属性,它现在看起来像这样[&#34; al20&#34;,&#34; b234&#34;]
因此,当我在Ransack搜索栏中键入al20时,我收到此错误。
user_rep_code_list_cont
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.
同样,我不是Ransack专家,但这似乎是现在应该涵盖的事情。我想在作为Array的模型上搜索属性。任何帮助都会非常感谢!
答案 0 :(得分:2)
我最终在这种情况下使用自定义Ransacker
:
ransacker :rep_code_list do
Arel.sql("array_to_string(rep_code_list, ',')")
end
这会将数组转换为字符串,以便Ransack可以使用cont
谓词进行搜索。不确定这是否是最好的方法,但它适用于我的情况。
答案 1 :(得分:1)
使用数组和Ransack并不是那么简单,您必须手动完成大量工作,因为基础查询会快速将您带入高级领域。检查数组中的成员资格是relatively easy,根据LIKE模式检查数组的每个元素是somewhat more complicated,因为您需要对unnest
函数调用执行LATERAL JOIN来解包数组,以便你可以喜欢它的成员:
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)
来清理从查询的其他部分出现的任何重复项:
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
功能做一些事情来压扁阵列,但是你必须处理分隔符,你仍然会遇到一个& #34;做到这一切&#34;范围(或者可能是自定义搜索者)。