Activeadmin: how to filter for strings that match two or more search terms

喜你入骨 提交于 2019-12-05 04:55:30

there is simple solution using ranasckable scopes

So put something like this in your model

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

After this you can add filter with AA DSL

Like

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

UPD

should work if change email_contains_any to email_includes

I've figured out a solution but it's not pretty.

The good news is that Ransack has no trouble with multiple terms searches. These searches use the 'predicate' cont_all. The following line works for finding emails containing 'smith' and '.edu'.

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

Since these searches are easy in Ransack, they're probably straightforward in Activeadmin, right? Wrong! To get them working, I needed to do three things.

  1. I put a custom ransack method (a.k.a. ransacker) into User.rb. I named the ransacker email_multiple_terms.

    class User < ActiveRecord::Base
    
    # ...
    
    ransacker :email_multiple_terms do |parent|
      parent.table[:path]
    end
    
  2. I declared a filter in my activeadmin dashboard, and associated it with the ransacker. Note that the search predicate cont_all is appended to the ransacker name.

admin/User.rb:

ActiveAdmin.register User do

# ...

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

This line creates the filter widget in Activeadmin. We're nearly there. One problem left: Activeadmin sends search queries to ransack as a single string (e.g. "smith .edu"), whereas our ransacker wants the search terms as an array. Somewhere, we need to convert the single string into an array of search terms.

  1. I modified activeadmin to split the search string under certain conditions. The logic is in a method that I added to 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
    

I then called this method inside apply_filtering.

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

This code is live in my own fork of activeadmin, here: https://github.com/d-H-/activeadmin

So, to get multiple term search working, follow steps 1 and 2 above, and include my fork of A.A. in your Gemfile:

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

HTH.

If anyone's got a simpler method, please share!

Just add three filters to your model:

filter :email_cont
filter :email_start
filter :email_end

It gives you a flexible way to manage your search.

This filter executes next sql code:

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

I expect that exactly what you're looking for.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!