How to add custom filter to Active Admin?

54,183

Solution 1

Active Admin uses the meta_search gem for its filters. ORed conditions syntax allows to combine several fields in one query, for example

Promo.metasearch(:name_or_address_contains => 'brooklyn')

In Active Admin DSL this translates to

ActiveAdmin.register Promo do

  filter :name_or_address, :as => :string

end

Solution 2

Active admin uses metasearch. For example you can do this:

filter :"subscription_billing_plan_name" , :as => :select, :collection => BillingPlan.all.map(&:name)

Solution 3

To use a custom filter, you can create a scope function and add it as search_methods in the model.

For example, on my User model:

search_methods :role_eq
scope :role_eq, -> (role) { where("? LIKE ANY(roles)", role) }

Then in users.rb, I can use my scope as a custom filter:

filter :role, label: "Roles", as: :select, collection: %w[ student teacher parent ]

Solution 4

Another way of doing such filtering in newer version of active admin:

# app/admin/my_model.rb
filter :my_custom_filter,
as: :numeric,
label: 'Custom Filter',
filters: [:eq]

Then add following 2 functions in your model file

Your filtering logic:

def self.my_custom_filter_eq(value)
  where(column_1: value) # or probably a more complex query that uses the value inputted by the admin user
end

Registering new filter for Ransack

def self.ransackable_scopes(_auth_object = nil)
  %i(my_custom_filter_eq)
end

Solution 5

Answering in 2018. ActiveAdmin uses Ransack.

On model itself you need to add Ransack formatter:

ransacker :my_custom_filter, formatter: -> (category_id) {
    ids = MyModel.where(category_id: category_id).pluck(:id) # return only id-s of returned items.
    ids.present? ? ids : nil # return ids OR nil!
} do |parent| # not sure why this is needed .. but it is :)
    parent.table[:id]
end 

In ActiveAdmin file you need to specify the rule:

filter :my_custom_filter_in, as: :select, collection: -> { Category.all } # sometimes my_custom_filter_eq - depending on what you want .. Specify different "as" when you need it. 
Share:
54,183
dkobozev
Author by

dkobozev

Updated on March 09, 2020

Comments

  • dkobozev
    dkobozev about 4 years

    Active Admin allows me to define filters that are displayed on the index page like so:

    ActiveAdmin.register Promo do
    
      filter :name
      filter :address
      filter :city
      filter :state
      filter :zip
    
    end
    

    I would like to combine all the fields above into one, so that I can search for Promos that contain the search string in name or full address. My model already has a named scope that I can use:

    class Promo < ActiveRecord::Base
      scope :by_name_or_full_address, lambda { |q| where('name LIKE :q OR address LIKE :q OR city LIKE :q OR state LIKE :q OR zip LIKE :q', :q => "%#{q}%") }
    end
    
  • mkirk
    mkirk over 10 years
    note that you probably want your collection to be re-evaluated every time the page loads by putting in a lambda: collection: lambda { BillingPlan.all.map(&:name) }. Otherwise if you add a BillingPlan after your app boots, it won't be in the selection.
  • Adam Prescott
    Adam Prescott over 10 years
    Although it uses Ransack it seems to still support this kind of filter. In my testing, you need to explicitly state as: :string. You can also pass label: "Custom Label" if you want a different label.
  • Skully
    Skully about 10 years
    getting a wrong number of arguments error (1 for 0) if i use a lambda statement, idea why? Using rails 3.2.17 with active_admin 0.6
  • Ain Tohvri
    Ain Tohvri over 9 years
    Throws syntax error, unexpected tIDENTIFIER, expecting '}' (SyntaxError)
  • MegaTux
    MegaTux almost 7 years
    Nice for model enum fields
  • Gonzalo S
    Gonzalo S over 6 years
    use .pluck(:name) instead .map to avoid bringing unnecessary data from the database.
  • MegaTux
    MegaTux over 4 years
    Ransack uses ransackers instead of search_methods for customization