An open API service indexing awesome lists of open source software.

https://github.com/simplificator/simplificator-filter

An attempt to generalize filtering of AR objects
https://github.com/simplificator/simplificator-filter

Last synced: about 1 year ago
JSON representation

An attempt to generalize filtering of AR objects

Awesome Lists containing this project

README

          

h1. Simplificator Filter

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

h2. Install


gem install simplificator-filter

h2. Usage

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

h2. Filter

h3. Definition

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
end

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:


default_filters_for_all_attributes

h3. filter_by

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 => 1.day.ago.to_date)

filter_by returns a scope, therefore you can use it with your other scopes or with will_paginate.


Product.cheap.filter_by(:fuzzy_name => 'carpet').red
Product.cheap.filter_by(:fuzzy_name => 'carpet').red.paginate(:page => 2)

h3. Associations

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 => 'customer.name'
filter.product_name :strategy => :like, :attribute => 'product.name'
filter.purchased_at :strategy => :equal
end

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


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

h3. 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]

h3. View Helpers

h3. Filter Strategies

table.
{font-weight:bold}.|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 |

h3. Patterns

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


filter_definition do |filter|
filter.name :strategy => [:begins_with, :ends_with]
filter.price
end

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.

Patterns

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

h2. Order