ClassyFilter
ClassyFilter is a customizeable class-based filtering library. Currently it's only build for Sequel, but there are plans to expand!
Installation
Add this line to your application's Gemfile:
gem 'classy_filter'
And then execute:
$ bundle
Or install it yourself as:
$ gem install classy_filter
Usage
Writing a filter
To begin using this gem, you must first define your filter class, deriving it from ClassyFilter::Base. In this class, you'd specify your filter fields, extra predicates and coercions (should you need those).
Let's begin with an example. Assuming you have a table named people with this structure:
| name | type |
|---|---|
| first_name | varchar(1023) |
| last_name | varchar(1023) |
| date_of_birth | date |
| trust_level | integer |
You could write a filter like this:
class MyFilter < ClassyFilter::Base
filter_field :first_name # (1)
filter_field :last_name_prefix, attribute: :last_name, predicate: :starts_with_i # (2)
filter_field :dob_after, attribute: :date_of_birth, predicate: :gteq, coercion: :integer # (3)
filter_field :rough_trust, attribute: :trust_level, predicate: :gt_10x, coercion: :integer # (4)
predicate :gt_10x, ->(dataset, attr, input) { dataset.where { |r| Sequel[attr] > input } } # (5)
end
Let's walk through this filter line by line.
Line (1) shows us how to define a very basic filter. This definition lets our filter accept the first_name parameter
and perform simple filtering by equality or inclusion.
Line (2) shows us how to define a filter with a custom predicate and parameter name. Our filter will accept the
last_name_prefix parameter and filter by the last_name column, using ILIKE to do it.
Line (3) shows us how to define a filter not just with a custom predicate, but also with a coercion. Before performing
the filtering, our filter will attempt to coerce the dob_after parameter into an Integer.
Line (5) shows us a custom predicate (that's used on the line (4)). A predicate is defined using the
ClassyFilter::Base.predicate method that accepts the predicate name and a proc that receives the dataset, the
attribute name and the parameter value.
You can see all existing predicates here and all existing coercions here.
Performing the filtering
This one is actually quite easy. Assuming we have a database named DB and receive a hash named params from somewhere
(say, the URL query string), we can use our filter as follows:
ds = DB[:people]
MyFilter.new(params).call(ds)
Development
After checking out the repo, run bundle install to install dependencies. Then, run rake spec to run the tests. You can also run pry -rclassy_filter for an interactive prompt that will allow you to experiment.
TODO
❗ Add collection (array/hash) coercions
❗ Move the Sequel implementation out of the gem
⬜ Try to find out a way to simplify predicates definitions
⬜ More tests. Never enough tests.
❓ Add a better coercion library. Dry-rb? Or maybe Hashie?
Contributing
Bug reports and pull requests are welcome on GitLab at https://gitlab.com/art-solopov/classy_filter.