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

时间:2015-10-23 19:09:41

标签: ruby-on-rails activerecord activeadmin ransack

让我们说我的用户类带有:email字段。我们假设我使用activeadmin来管理用户。

制作一个过滤器,返回与一个字符串匹配的电子邮件,例如"史密斯",非常简单。在admin/user.rb中,我只包含

filter :email 

这为我提供了一个完成工作的过滤器小部件。

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

Google告诉我,activerecord使用了RansackRansack demo有一个' advanced'允许多项搜索的模式。

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

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

3 个答案:

答案 0 :(得分:7)

使用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"

UPD

如果将email_contains_any更改为email_includes

应该有效

答案 1 :(得分:6)

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

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

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

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

  1. 我将自定义搜索方法(a.k.a。ransacker)放入User.rb。我将搜索者命名为email_multiple_terms

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

  3. admin/User.rb

    ActiveAdmin.register User do
    
    # ...
    
    filter :email_multiple_terms_cont_all, label: "Email", as: :string 
    

    此行在Activeadmin中创建过滤器小部件。我们快到了。还剩一个问题:Activeadmin将搜索查询作为单个字符串发送到搜索范围(例如"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
      
    2. 然后我在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。

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

答案 2 :(得分:3)

只需在模型中添加三个过滤器:

filter :email_cont
filter :email_start
filter :email_end

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

enter image description here

此过滤器执行下一个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

我希望你正是在寻找它。