Activeadmin:如何过滤匹配两个或多个搜索词的字符串

dB'*_*dB' 8 activerecord ruby-on-rails activeadmin ransack

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

制作一个返回与一个字符串匹配的电子邮件的过滤器,例如"smith",非常简单.在admin/user.rb,我只是包括该行

filter :email 
Run Code Online (Sandbox Code Playgroud)

这给了我一个完成工作的过滤器小部件.

但是,此过滤器不允许我搜索多个项的交集.我可以搜索包含"smith"的电子邮件,但不能搜索包含"smith"和".edu"的电子邮件.

Google告诉我,activerecord 在引擎盖下使用Ransack,而Ransack演示具有允许多个术语搜索的"高级"模式.

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

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

Fiv*_*ell 7

使用可运行的范围有简单的解决方案

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

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
Run Code Online (Sandbox Code Playgroud)

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

喜欢

  filter :email_includes, as: :string, label: "Email"
Run Code Online (Sandbox Code Playgroud)

UPD

如果变化应该工作email_contains_anyemail_includes

  • 它应该记录在ransack中(AA只使用ransack),使用可搜索的范围你可以构建你想要的任何逻辑,不仅是多项搜索,是的我也喜欢它 (2认同)

dB'*_*dB' 6

我已经找到了解决方案,但它并不漂亮.

好消息是,Ransack在多项搜索方面没有任何问题.这些搜索使用'谓词' cont_all.以下行用于查找包含"smith"和".edu"的电子邮件.

User.ransack(email_cont_all: ['smith','.edu'] ).result
Run Code Online (Sandbox Code Playgroud)

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

  1. 我把一个自定义的搜索方法(又名ransacker)放入User.rb.我给这个洗劫者起了个名字email_multiple_terms.

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

admin/User.rb:

ActiveAdmin.register User do

# ...

filter :email_multiple_terms_cont_all, label: "Email", as: :string 
Run Code Online (Sandbox Code Playgroud)

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

  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
    
    Run Code Online (Sandbox Code Playgroud)

然后我在里面调用了这个方法apply_filtering.

    def apply_filtering(chain)
      @search = chain.ransack split_search_params clean_search_params params[:q]
      @search.result
    end
Run Code Online (Sandbox Code Playgroud)

这段代码存在于我自己的activeadmin分支中,在这里:https://github.com/dH-/activeadmin

因此,要使多项术语搜索工作,请按照上面的步骤1和2,在我的Gemfile中包含我的AA分支:

  gem 'activeadmin', :git => 'git://github.com/d-H-/activeadmin.git'
Run Code Online (Sandbox Code Playgroud)

HTH.

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