QueryFilter
This gem provides DSL to write custom complex filters for ActiveRecord models. It automatically parses whitelisted params and adds filters to query.
Instead of writing this:
class Order < ActiveRecord::Base
def self.filter(params)
query = all
query = query.with_state(params[:state]) if params[:state].present?
query
end
end
you can write this:
class Order < ActiveRecord::Base
def self.filter(params)
OrderFilter.new(all, params).to_query
end
end
Installation
Add this line to your application's Gemfile:
gem 'query_filter'
And then execute:
$ bundle
Or install it yourself as:
$ gem install query_filter
Usage
This gem support next types of filter params:
scope - simple filter by column
scope :state def scope_state(value) # your code endKeyword
scopedefines type of filter, and argument:stateis a key from params to use for filter. Can be restricted using array of allowed valuesrange - between, greater than or equal, less than or equal For range inputs, can be used with 2 arguments or with 1, for example if both params supplied as
{ price_from: 100, price_to: 200 }this will produce a query like
orders.price BETWEEN 100 AND 200With one parameter
price_froma query would look like:orders.price >= 100or
price_to:orders.price <= 200splitter range - the same as range, but with one param Some JS slider libraries join ranges with splitter, this filter could be used for that. Sample params:
{ price: '100;200' }query:
orders.price BETWEEN 100 AND 200date range - the same as range, but for dates Sample params:
{ created_at: '06/24/2017 to 06/30/2017' }query:
orders.created_at BETWEEN '2017-06-24 04:00:00.000000' AND '2017-07-01 03:59:59.999999'order by
order_by :sort_column, via: :sort_mode def order_by_sort_column(column, direction) # your code endSample params:
{ sort_column: 'created_at', sort_mode: 'desc' }query:
ORDER BY "orders"."created_at" DESC
Sample class with usage examples
To use scope filter with Order model define your filter class as app/filters/order_filter.rb
class OrderFilter < QueryFilter::Base
# can be restricted using array of values
scope :state, only: [:pending, :completed]
scope :deleted, only: TRUE_ARRAY
scope :archived, if: :allow_archived?
range :price
splitter_range :price
date_range :created_at
order_by :sort_column, via: :sort_mode
# Filter will be applied when following params present
# { state: :pending }
def scope_state(value)
query.with_state(value)
end
def scope_deleted(_value)
query.where(deleted: true)
end
def scope_archived(_)
query.where(archived: true)
end
# Filter will be applied when following params present
# { price_from: 100, price_to: 200 }
def range_price(range)
# You should pass SQL column name to `query` method
# this will result with following query:
# 'orders.price BETWEEN 100 AND 200'
query.where(range.query('orders.price'))
end
def splitter_range_price(values)
# 'orders.price BETWEEN 100 AND 200'
query.where(price: value.range)
end
def date_range_created_at(period)
query.where(created_at: period.range)
end
def order_by_sort_column(column, direction)
query.reorder("orders.#{column} #{direction} NULLS LAST")
end
protected
def allow_archived?
@params[:old] == '1' || params[:state] == 'archived'
end
end
Configuration
You can set up some options in general
# config/initializers/query_filter.rb
QueryFilter.setup do |config|
# Date period format, by default: %m/%d/%Y
config.date_period_format = '%d-%m-%Y'
# Splitter to parse date period values, by default 'to'
config.date_period_splitter = 'until'
end
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/query_filter.
License
The gem is available as open source under the terms of the MIT License.