EasyFilters
This gem provides a simple API for defining dynamic persistent(in session) filters based on active record models.
Installation
Add this line to your application's Gemfile:
gem 'easy_filters'
And then execute:
$ bundle
Usage
Create a articles_filter.rb
file in app/models/easy_filters
folder
EasyFilters expects you to define the following methods:
module EasyFilters
class ArticlesFilter < ModelFilter
# Default values for this filter.
def self.defaults
{ body: nil, date_from: nil, date_to: nil }
end
# Model class to be filtered.
def model
Article
end
end
end
- defaults: defines the fields that will be used for filtering and its defaults values
- model: returns the target class to be filtered
Customizing filtering strategy
For defining the parts of the query that will filter each each field,
define a method named filter_by_#{field_name}
.
The field must be present in the defaults array.
Each filter_by_*
method receives 2 params:
- scope: The actual query.
- value: The value for the current field
For example:
module EasyFilters
class ArticlesFilter < ModelFilter
#(...) previously defined methods
# Custom filter method for :body field.
def filter_by_body(scope, value)
matcher = "%#{value}%"
scope.where('body like ? OR body like ?', matcher, matcher)
end
# The following 2 filter_by builds an from/to/between date filter:
# Custom filter method for :date_from field.
def filter_by_date_from(scope, value)
scope.joins(:editions).where('editions.date >= ?', Date.parse(value))
end
# Custom filter method for :date_to field.
def filter_by_date_to(scope, value)
scope.joins(:editions).where('editions.date <= ?', Date.parse(value))
end
end
end
Usage in controllers
You can instance a filter in your controller, and define some usefull methods
For example:
#(...) previously defined controller
before_action :filter, only: [:filter_page]
before_action :clear_filter, only: [:filter_page]
def filter_page
@objects = @filter.all
end
private
def create_filter(filter_class, opts = {})
= { store: session, persist: true }.merge opts
filter_class.new
end
def filter_params
if params.has_key?(:filter)
params.require(:filter).permit(:body, :date_from, :date_to).
end
end
# Create the @filter object with the currently-set values for the filters
def filter
@filter = create_filter EasyFilters::ArticlesFilter, values: filter_params
end
# Clear the currently-set filters, restoring them to the defaults
def clear_filter
if params[:commit] == t('common.filters.clear')
@filter.clear!
redirect_to request.path
end
end
Usage in views
Define a input with the filter
<% form_tag '', :method => :get do %>
<%= label :filter, :body %>
<%= text_field :filter, :body %>
<%= submit_tag t('common.filters.search') %>
<%= submit_tag t('common.filters.clear') %>
<% end %>