Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

An attempt to generalize filtering of AR objects

branch: master

Simplificator Filter

An Extension to ActiveRecord in order to manage filtering and ordering of collections.


  gem install simplificator-filter


You can define filters and orders in your models and then using this definitions to retrieve the data.
See the examples below.



Assume you have a product model with name:string, price:integer and available_as_of:date as attributes. Then you could define the following filter definition in your product class.

filter_definition do |filter|
filter.fuzzy_name :strategy => :like, :attribute => ‘name’
filter.price_range :strategy => :between, :attribute => ‘price’
filter.available_as_of :strategy => :equal

You can use different strategies according to the attributes type. For string you can define :like, :begins_with, :ends_with or :equal.
The strategy option is not mandatory, if not set then the default strategy for that attributes type is used. For a string type this would be the :like strategy.
(See filter strategies for more information)

If you just want a filter with the same name as the attribute and its default strategy, you can use:

  default_filter_for_attribute :name
  default_filters_for_attributes :name, :price

or just define for all your attributes a default filter:



Keeping the first definition as example, you can now use the filter_by class method:

  Product.filter_by(:fuzzy_name => 'carpet')
  Product.filter_by(:fuzzy_name => 'carpet', :price_range => '15 - 45')
  Product.filter_by(:fuzzy_name => 'carpet', :price_range => '15 - 45', :available_as_of =>

filter_by returns a scope, therefore you can use it with your other scopes or with will_paginate. => 'carpet').red => 'carpet').red.paginate(:page => 2)


You can even filter associated attributes. Let’s add an order model with following associations and filter definition.

  belongs_to :product
  belongs_to :customer

  filter_definition do |filter|
    filter.customer_name :strategy => :like, :attribute => ''
    filter.product_name :strategy => :like, :attribute => ''
    filter.purchased_at :strategy => :equal

The filter_by works still the same way, all necessary tables are included automatically.

  Product.filter_by(:customer_name => 'foo', :product_name => 'magic carpet')

Filter Forms

  <% form_for @products.filter |f| %>
    <%= f.input_field f.fuzzy_name %>
    <%= f.input_field f.price_range %>
    <%= f.input_field f.purchased_at %>
    <%= f.sumbit_tag 'Filter' %>
  <% end %>

In your controller you can just use:

@products = Product.filter_by params[:filter]

View Helpers

Filter Strategies

Type strategies default
string :like, :begins_with, :ends_with, :like
text :like, :begins_with, :ends_with, :like
integer :equal, :between :equal
float :equal, :between :equal
time :equal, :between :equal
date :equal, :between :equal
datetime :equal, :between :equal
binary :equal, :equal
boolean :equal, :equal


If you define more than one strategy for an attribute or leave it completly.

  filter_definition do |filter| :strategy => [:begins_with, :ends_with]

In this cases filter_by tries to match a pattern against the passed value to detect the right strategy.
If name matches “* carpet” a :ends_with strategy would be applied, if it would match "magic* " a :begins_with would be used.
If no pattern matches, then default strategy is used.
The only difference between the first and the second filter definition is: If a pattern could be found but it is not included in the array passed, an ArgumentError will be raised.


pattern strategy
/^\(.?)\*$/ :like
/^\(.?)$/, :ends_with
/^(.?)\$/, :begins_with
/^(-?\d+)\s?-\s?(-?\d+)$/ :between


Something went wrong with that request. Please try again.