class Rack::Reducer
Declaratively filter data via URL params, in any Rack
app, with any ORM.
Constants
- EMPTY_PARAMS
- VERSION
Public Class Methods
call(params, dataset:, filters:)
click to toggle source
Call Rack::Reducer
as a function instead of creating a named reducer
# File lib/rack/reducer.rb, line 16 def call(params, dataset:, filters:) new(dataset, *filters).apply(params) end
new(dataset, *filters)
click to toggle source
Instantiate a Reducer
that can filter `dataset` via `#apply`. @param [Object] dataset an ActiveRecord::Relation, Sequel::Dataset,
or other class with chainable methods
@param [Array<Proc>] filters An array of lambdas whose keyword arguments
name the URL params you will use as filters
@example Create a reducer and use it in a Sinatra app
DB = Sequel.connect(ENV['DATABASE_URL']) MyReducer = Rack::Reducer.new( DB[:artists], lambda { |name:| where(name: name) }, lambda { |genre:| where(genre: genre) }, ) get '/artists' do @artists = MyReducer.apply(params) @artists.to_json end
# File lib/rack/reducer.rb, line 39 def initialize(dataset, *filters) @dataset = dataset @filters = filters @default_filters = filters.select do |filter| filter.required_argument_names.empty? end end
Public Instance Methods
apply(url_params)
click to toggle source
Run `@filters` against `url_params` @param [Hash, ActionController::Parameters, nil] url_params
a Rack-compatible params hash
@return `@dataset` with the matching filters applied
# File lib/rack/reducer.rb, line 51 def apply(url_params) if url_params.empty? # Return early with the unfiltered dataset if no default filters exist return fresh_dataset if @default_filters.empty? # Run only the default filters filters, params = @default_filters, EMPTY_PARAMS else # This request really does want filtering; run a full reduction filters, params = @filters, url_params.to_unsafe_h.deep_symbolize_keys end reduce(params, filters) end
Private Instance Methods
fresh_dataset()
click to toggle source
Rails Model.all
relations get query-cached by default, which has caused filterless requests to load stale data. This method busts the query cache. See github.com/chrisfrank/rack-reducer/issues/11
# File lib/rack/reducer.rb, line 82 def fresh_dataset @dataset.clone end
reduce(params, filters)
click to toggle source
# File lib/rack/reducer.rb, line 68 def reduce(params, filters) filters.reduce(fresh_dataset) do |data, filter| next data unless filter.satisfies?(params) data.instance_exec( **params.slice(*filter.all_argument_names), &filter ) end end