【问题标题】:Activeadmin: how to filter for strings that match two or more search termsActiveadmin:如何过滤匹配两个或多个搜索词的字符串
【发布时间】:2015-10-23 19:09:40
【问题描述】:

假设我有一个带有 :email 字段的 User 类。假设我正在使用 activeadmin 来管理用户。

制作一个过滤器,返回匹配一个字符串的电子邮件,例如“史密斯”,很简单。在admin/user.rb 中,我只包含了这一行

filter :email 

这给了我一个过滤器小部件来完成这项工作。

但是,此过滤器不允许我搜索多个术语的交集。我可以搜索包含“smith”的电子邮件,但不能搜索同时包含“smith”和“.edu”的电子邮件。

Google 告诉我,activerecord 在后台使用Ransack,而Ransack demo 具有允许多个术语搜索的“高级”模式。

将多词搜索小部件放入 activeadmin 的最简单方法是什么?

理想情况下,我想要一个允许我输入 smith .edusmith AND .edu 以过滤包含这两个术语的电子邮件的小部件。

【问题讨论】:

  • 这看起来很相似:scriptscoop.net/t/2e4ac6d6ff33/…
  • 要使用多字段搜索,您可以使用filter :email_or_first_name_cont。我认为(从未尝试过,所以甚至不确定假设它会起作用是否合乎逻辑)您可以尝试filter :email_or_email_cont :)
  • 我用它就是这么简单,但filter :email_or_email_cont 似乎并没有完成这项工作。 :( 还是谢谢!

标签: ruby-on-rails activerecord activeadmin ransack


【解决方案1】:

有一个使用 ranasckable 范围的简单解决方案

所以在你的模型中加入这样的东西

class User < ActiveRecord::Base
    ....
    scope :email_includes, ->(search) {
       current_scope = self
       search.split.uniq.each do |word|
         current_scope = current_scope.where('user.email ILIKE ?', "%#{word}%")  
       end
       current_scope
    }

    def self.ransackable_scopes(auth_object = nil)
      [ :email_includes]
    end
end

在此之后,您可以使用 AA DSL 添加过滤器

喜欢

  filter :email_includes, as: :string, label: "Email"

更新

如果将 email_contains_any 更改为 email_includes 应该可以工作

【讨论】:

  • 当我在控制台中运行这些搜索时,它们可以工作,但我无法让它们在 activeadmin 中工作。 AA 不会将搜索字符串拆分为一组术语。我仍然需要使用我的自定义 AA 前叉。我做错了吗?
  • @dB',由于某些原因我们不能使用_any,请将email_contains_any 更改为email_includes
  • 啊,谢谢!这行得通,而且它是比我的更好的解决方案。这在任何地方都有记录吗? activerecord 文档是否解释了如何进行这些多词搜索?
  • 它应该记录在 ransack 中(AA 只使用 ransack),使用 ransackable 范围,您可以构建任何您想要的逻辑,不仅是多词搜索,是的,我也喜欢它
  • 我希望我能多次投票!我需要的是通过电子邮件地址列表过滤的能力,所以我做了arr = search.downcase.split(/[ \n]/) 然后current_scope = current_scope.where(email: arr)
【解决方案2】:

我想出了一个解决方案,但它并不漂亮。

好消息是 Ransack 对多个字词搜索没有任何问题。这些搜索使用“谓词”cont_all。以下行适用于查找包含“smith”和“.edu”的电子邮件。

User.ransack(email_cont_all: ['smith','.edu'] ).result

由于这些搜索在 Ransack 中很容易,因此在 Activeadmin 中它们可能很简单,对吧?错误的!为了让它们发挥作用,我需要做三件事。

  1. 我在User.rb 中加入了一个自定义的搜查方法(又名ransacker)。我将洗劫者命名为email_multiple_terms

    class User < ActiveRecord::Base
    
    # ...
    
    ransacker :email_multiple_terms do |parent|
      parent.table[:path]
    end
    
  2. 我在我的 activeadmin 仪表板中声明了一个过滤器,并将其与 ransacker 相关联。请注意,搜索谓词 cont_all 附加到 ransacker 名称。

admin/User.rb:

ActiveAdmin.register User do

# ...

filter :email_multiple_terms_cont_all, label: "Email", as: :string 

这一行在 Activeadmin 中创建过滤器小部件。我们快到了。还有一个问题:Activeadmin 将搜索查询作为单个字符串(例如 "smith .edu")发送到 ransack,而我们的 ransacker 想要将搜索词作为数组。在某个地方,我们需要将单个字符串转换为搜索词数组。

  1. 我修改了 activeadmin 以在某些条件下拆分搜索字符串。逻辑在我添加到 lib/active_admin/resource_controller/data_access.rb 的方法中。

    def split_search_params(params)
      params.keys.each do |key|
        if key.ends_with? "_any" or key.ends_with? "_all"
          params[key] = params[key].split  # turn into array
        end
      end
      params
    end
    

然后我在apply_filtering 内部调用了这个方法。

    def apply_filtering(chain)
      @search = chain.ransack split_search_params clean_search_params params[:q]
      @search.result
    end

此代码位于我自己的 activeadmin 分支中,这里:https://github.com/d-H-/activeadmin

因此,要使多个词条搜索正常工作,请按照上面的步骤 1 和 2 进行操作,并包括我的 A.A. 分支。在您的 Gemfile 中:

  gem 'activeadmin', :git => 'git://github.com/d-H-/activeadmin.git'

HTH。

如果有人有更简单的方法,请分享!

【讨论】:

    【解决方案3】:

    只需向您的模型添加三个过滤器:

    filter :email_cont
    filter :email_start
    filter :email_end
    

    它为您提供了一种灵活的方式来管理您的搜索。

    这个过滤器执行下一条sql代码:

    SELECT  "admin_users".* FROM "admin_users"
    WHERE ("admin_users"."email" ILIKE '%smith%' AND 
           "admin_users"."email" ILIKE '%\.edu')
    ORDER BY "admin_users"."id" desc LIMIT 30 OFFSET 0
    

    我希望这正是您正在寻找的。​​p>

    【讨论】:

    • 这很接近,但我实际上需要在电子邮件中匹配多个查询的东西。在开头、中间和结尾搜索对我来说并不完全合适。 :(谢谢,寿。
    猜你喜欢
    • 1970-01-01
    • 2014-03-14
    • 2017-12-17
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2015-04-08
    • 2018-06-07
    • 1970-01-01
    相关资源
    最近更新 更多