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

Say I have a User class with a field: email. And let me say that I use activeadmin to manage users.

Creating a filter that returns emails matching a single line, for example. "blacksmith" is very simple. In admin/user.rb I just include the line

 filter :email 

This gives me a filter widget that does the job.

However, this filter does not allow me to search for the intersection of several terms. I can search for emails containing "blacksmith", but not for letters containing both "blacksmith" and ".edu".

Google tells me that activerecord uses Ransack under the hood, and Ransack Demo has an “advanced” mode that allows multiple searches to be performed.

What is the easiest way to get a multi-user search widget in activeadmin?

Ideally, I would like the widget to let me type smith .edu or smith AND .edu to filter email messages containing both terms.

+5
source share
3 answers

there is a simple solution using runasckable rows

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 that you can add a filter using DS DSL

how

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

UPD

should work if you change email_contains_any to email_includes

+4
source

I figured out a solution, but it’s not very.

The good news is that Ransack has no problem finding multiple terms. The search uses the predicate cont_all . The next line works to find emails containing "blacksmith" and ".edu".

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

Since these searches in Ransack are easy, they are probably straightforward in Activeadmin, right? Wrong! To make them work, I had to do three things.

  • I put the special ransack (aka ransacker ) method in User.rb I called ransacker email_multiple_terms .

     class User < ActiveRecord::Base # ... ransacker :email_multiple_terms do |parent| parent.table[:path] end 
  • I declared a filter in my activeadmin control panel and linked it to ransacker. Note that the search predicate cont_all appended to the name ransacker.

admin/User.rb :

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

This line creates a filter widget in Activeadmin. We are almost there. One problem remains: Activeadmin sends search queries to a regular string (for example, "smith .edu" ), while our ransacker wants the search terms to be an array. Somewhere we need to convert a single string into an array of search terms.

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

Then I 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 in my own activeadmin plugin, here: https://github.com/dH-/activeadmin

So, to get it working with multiple terms, follow steps 1 and 2 above and turn on my AA plug in your Gemfile:

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

NTN.

If anyone got a simpler method, please share!

+6
source

Just add three filters to your model:

 filter :email_cont filter :email_start filter :email_end 

This gives you a flexible way to manage your search.

enter image description here

This filter executes the following 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 exactly what you are looking for.

+3
source

Source: https://habr.com/ru/post/1234399/


All Articles