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
- Host: GitHub
- URL: https://github.com/simplificator/simplificator-filter
- Owner: simplificator
- License: mit
- Created: 2010-07-21T09:54:54.000Z (about 16 years ago)
- Default Branch: master
- Last Pushed: 2012-03-15T11:23:08.000Z (over 14 years ago)
- Last Synced: 2025-06-02T15:51:19.588Z (about 1 year ago)
- Language: Ruby
- Homepage:
- Size: 146 KB
- Stars: 1
- Watchers: 4
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.textile
- License: LICENSE
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