首页 > 解决方案 > 使用 arel_predicates 和正则表达式编写带有 ransack 的自定义过滤器 (RoR 6)

问题描述

我有一个名为'employee'的模型,我正在使用gem'ancestry'。

基本上,这个 gem 所做的是将ancestors_ids这个员工的所有(父母)数据“存储”在一个名为 this 的字符串列'ancestry'"1/2/3"。因此,如果员工的祖先看起来像"1/2/3",则意味着他的祖先是员工的 id 为3(parent)、2(parent of 3) 和1(parent of 2)。

我有一个用 ransack 编写的自定义过滤器,如下所示:

  ransacker :managers_ids, type: :integer do
    Arel.sql("replace(employees.ancestry, '/', ' ')")
  end

我有一个使用 arel_predicates 的自定义搜索方法,如下所示:

Ransack.configure do |config|
  config.add_predicate 'special_in',
    arel_predicate: 'matches_regexp',
    # Converts string array into array and join with | that are OR in regex SQL
    formatter: proc { |v| "#{JSON.parse(v).join("|")}"},
    type: :array
end

当我将此过滤器与 ransack 一起应用时,如下所示:q[managers_ids_special_in][]=1 2 3它的作用是将/列中的所有破折号替换为空格,留下一个看起来像“1 2 3”的字符串,然后special_in谓词用于'matches_regexp'在祖先列中查找值匹配我在数组中发送的那些。

这“有效”。问题是,如果我的祖先列看起来像"11/22/33/1/2/3"并且我使用q[managers_ids_special_in][]=1 2 3了 ,这将匹配所有值,因为'special_in'将“1”与“11”匹配,“2”与“22”匹配,“3”与“33”匹配。

我想避免这种情况,我一直在尝试不同的谓词,或者尝试“改变”我当前的解决方案来实现这一点,但这有点超出我的理解。我希望你们中的任何一个对洗劫和 arel 更有经验的人都可以在这里帮助我。也许指出我正确的方向,或者向我解释为什么这种方式不起作用,所以我可以找到解决方案。

这些是我试图用来实现我的目标的 arel 谓词:

https://github.com/rails/arel/blob/208fe3690d840d0ee65b1395a891886e58fd3f4b/lib/arel/predications.rb#L126

我还发现了这个:

https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/adapters/active_record/ransack/constants.rb

但正如我所说,我看到了很多信息并且真的不知道如何使用它(现在已经在轨道上大约 7 个月了)

提前感谢您的帮助,我很感激。

标签: ruby-on-railsrubyransack

解决方案


推荐阅读