Filterameter
Declarative Filter Parameters for Rails Controllers.
Usage
Declare filters at the top of controllers to increase readability and reduce boilerplate code. Filters can be declared for attributes, scopes, or attributes from singular associations (belongs_to
or has_one
). Validations can also be assigned.
filter :color
filter :size, validates: { inclusion: { in: %w[Small Medium Large] }, unless: -> { size.is_a? Array } }
filter :brand_name, association: :brand, name: :name
filter :on_sale, association: :price, validates: [{ numericality: { greater_than: 0 } },
{ numericality: { less_than: 100 } }]
Filtering Options
The following options can be specified for each filter.
name
If the name of the parameter is different than the name of the attribute or scope, then use the name parameter to specify the name of the attribute or scope. For example, if the attribute name is current_status
but the filter is exposed simply as status
use the following:
filter :status, name: :current_status
association
If the attribute or scope is nested, it can be referenced by naming the association. Only singular associations are valid. For example, if the manager_id attribute lives on an employee's department record, use the following:
filter :manager_id, association: :department
validates
If the filter value should be validated, use the validates
option along with ActiveModel validations. Here's an example of the inclusion validator being used to restrict sizes:
filter :size, validates: { inclusion: { in: %w[Small Medium Large] }, unless: -> { size.is_a? Array } }
Note that the inclusion
validator does not allow arrays to be specified. If the filter should allow multiple values to be specified, then the validation needs to be disabled when the value an array.
partial
Specify the partial option if the filter should do a partial search (SQL's LIKE
). The partial option accepts a hash to specify the search behavior. Here are the available options:
- match: anywhere (default), from_start, dynamic
- case_sensitive: true, false (default)
There are two shortcuts: : the partial option can be declared with true
, which just uses the defaults; or the partial option can be declared with the match option directly, such as partial: :from_start
.
filter :description, partial: true
filter :department_name, partial: :from_start
filter :reason, partial: { match: :dynamic, case_sensitive: true }
The match
options defines where you are searching (which then controls where the wildcard(s) appear):
- anywhere: adds wildcards at the start and end, for example '%blue%'
- from_start: adds a wildcard at the end, for example 'blue%'
- dynamic: adds no wildcards; this enables the client to fully control the search string
Configuring Controllers
Rails conventions are used to determine the controller's model as well as the name of the instance variable to apply the filters to. For example, the PhotosController will use the variable @photos
to store a query against the Photo model. If the conventions do not provide the correct info, they can be overridden with the following two methods:
filter_model
Provide the name of the model. This method also allows the variable name to be optionally provided as the second parameter.
filter_model 'Picture'
filter_query_var_name
Provide the name of the instance variable. For example, if the query is stored as @data
, use the following:
filter_query_var_name :data
Installation
Add this line to your application's Gemfile:
gem 'filterameter'
And then execute:
$ bundle
Or install it yourself as:
$ gem install filterameter
Running Tests
Tests are written in RSpec and the dummy app uses a docker database. First, start the database and prepare it from the dummy folder.
cd spec/dummy
docker-compose up -d
bundle exec rails db:test:prepare
cd ../..
Run the tests from the main directory
bundle exec rspec
License
The gem is available as open source under the terms of the MIT License.