MergeFilter is a minimal DSL for filtering ActiveRecord objects. Instead of writing complex branching logic in your controllers, encapsulate that logic into a PORO.
Add this line to your application's Gemfile:
gem 'merge_filter'
And then execute:
$ bundle
Or install it yourself as:
$ gem install merge_filter
Imagine we have a listings model with a price_cents field.
Instead of complex branching logic:
class ListingsController < ApplicationController
def index
if params[:min_price]
Listing.where("price_cents >= ?", params[:min_price])
elsif params[:max_price]
Listing.where("price_cents <= ?", params[:max_price])
else
Listing.all
end
end
end
Or using multiple scopes:
class ListingsController < ApplicationController
def index
Listing.all.max_price(params[:max_price).min_price(params[:min_price])
end
end
Encapsulate your logic in a PORO
class ListingFilter
include MergeFilter
default_scope { Listing.all }
filter_by(:price_cents)
filter_by(:min_price) do |value, scope|
scope.where("price_cents >= ?", value)
end
filter_by(:max_price) do |value|
Listing.where("price_cents <= ?", value)
end
end
class ListingsController < ApplicationController
def index
ListingFilter.new(min_price: params[:min_price], max_price: params[:max_price]).records
end
end
- Classes that include the MergeFilter module need to implement a single default_scope method that takes a block, and as many filter_by methods as you like.
- The filter_by method takes two arguments. The first is the column which you want to filter by, the second is an optional block which must return an ActiveRecord relation object. If you leave off the block MergeFilter defaults to a
where
query. - To filter records, intitialize your MergeFilter object with a hash. The keys of the hash must correspond to the columns in the filter_by methods. The values get passed into their respective filter_by method.
- Call the records method when you want to return the corresponding records from your database.
- Fork it ( https://github.com/[my-github-username]/merge_filter/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request