Skip to content

Instantly share code, notes, and snippets.

@tinynumbers
Last active December 13, 2021 14:17
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save tinynumbers/7235594 to your computer and use it in GitHub Desktop.
Save tinynumbers/7235594 to your computer and use it in GitHub Desktop.

Saving ActiveAdmin filters between requests

This shows one technique for preserving filters on index pages for ActiveAdmin resources, without having to patch the ActiveAdmin core.

It restores any previously-used filters whenever the index page is rendered for a resource, unless the current request is an actual application of new filters. It also properly handles the clear-filters button (via a synchronous Ajax request that happens immediately before the normal filter form processing).

Yes, it's a bit of a hack, but it has worked well for me so far.

Usage

Place the controller.rb file in lib/active_admin/filter_saver/controller.rb, the index-filters.coffee somewhere that will be included into ActiveAdmin's JavaScripts. The active_admin.rb excerpt is from config/initializers/active_admin.rb.

ActiveAdmin.setup do |config|
# .... [SNIP] ....
# == Controller Filters
# These two are defined in ActiveAdmin::FilterSaver::Controller, which is loaded below.
config.before_filter :restore_search_filters
config.after_filter :save_search_filters
# .... [SNIP] ....
end
require 'active_admin/filter_saver/controller'
ActiveAdmin.before_load do |app|
# Add our Extensions
ActiveAdmin::BaseController.send :include, ActiveAdmin::FilterSaver::Controller
end
# -*- encoding : utf-8 -*-
module ActiveAdmin
module FilterSaver
# Extends the ActiveAdmin controller to persist resource index filters between requests.
#
# @author David Daniell / тιηуηυмвєяѕ <info@tinynumbers.com>
module Controller
private
SAVED_FILTER_KEY = :last_search_filter
def restore_search_filters
filter_storage = session[SAVED_FILTER_KEY]
if params[:clear_filters].present?
params.delete :clear_filters
if filter_storage
logger.info "clearing filter storage for #{controller_key}"
filter_storage.delete controller_key
end
if request.post?
# we were requested via an ajax post from our custom JS
# this render will abort the request, which is ok, since a GET request will immediately follow
render json: { filters_cleared: true }
end
elsif filter_storage && (params[:action].to_sym == :index) && params[:q].blank? && (params[:commit] != 'Filter')
saved_filters = filter_storage[controller_key]
unless saved_filters.blank?
params[:q] = saved_filters
end
end
end
def save_search_filters
if params[:action].to_sym == :index
session[SAVED_FILTER_KEY] ||= Hash.new
session[SAVED_FILTER_KEY][controller_key] = params[:q]
end
end
# Get a symbol for keying the current controller in the saved-filter session storage.
def controller_key
current_path = request.env['PATH_INFO']
current_route = Rails.application.routes.recognize_path(current_path)
current_route.sort.flatten.join('-').gsub(/\//, '_').to_sym
end
end
end
end
$ ->
# Extend the clear-filters button to clear saved filters
$('.clear_filters_btn').click (evt) ->
# This will send a synchronous post with clear_filters set to true -
# our AA FilterSaver controller extension looks for this parameter to
# know when to clear session-stored filters for a resource - and then
# the default AA clear-filters button behavior will issue a get request
# to actually re-render the page.
$.ajax this.href, {
async: false,
data: { clear_filters: true },
type: 'POST'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment