Module: Rack::Reducer

Defined in:
lib/rack/reducer.rb,
lib/rack/reducer/version.rb,
lib/rack/reducer/warnings.rb,
lib/rack/reducer/reduction.rb,
lib/rack/reducer/middleware.rb,
lib/rack/reducer/refinements.rb

Overview

Declaratively filter data via URL params, in any Rack app.

Defined Under Namespace

Modules: Warnings Classes: Middleware, Reduction

Constant Summary collapse

VERSION =
'1.1.2'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.call(params, dataset:, filters:) ⇒ Object

Filter a dataset without creating a Reducer first. Note that this approach is a bit slower and less memory-efficient than creating a Reducer via ::create. Use ::create when you can.

Examples:

Call Rack::Reducer as a function in a Sinatra app

get '/artists' do
  @artists = Rack::Reducer.call(params, dataset: Artist.all, filters: [
    lambda { |name:| where(name: name) },
    lambda { |genre:| where(genre: genre) },
  ])
end

Parameters:

  • params (Hash)

    Rack-compatible URL params

  • dataset (Object)

    A dataset, e.g. one of your App’s models

  • filters (Array<Proc>)

    An array of lambdas with keyword arguments



46
47
48
# File 'lib/rack/reducer.rb', line 46

def self.call(params, dataset:, filters:)
  Reduction.new(dataset, *filters).apply(params)
end

.create(dataset, *filters) ⇒ Object

Create a Reduction object that can filter dataset via #apply.

Examples:

Create a reducer and use it in a Sinatra app

DB = Sequel.connect(ENV['DATABASE_URL'])
MyReducer = Rack::Reducer.create(
  DB[:artists],
  lambda { |name:| where(name: name) },
  lambda { |genre:| where(genre: genre) },
)

get '/artists' do
  @artists = MyReducer.apply(params)
  @artists.to_json
end

Parameters:

  • dataset (Object)

    an ActiveRecord::Relation, Sequel::Dataset, or other class with chainable methods

  • filters (Array<Proc>)

    An array of lambdas whose keyword arguments name the URL params you will use as filters

Returns:

  • Rack::Reducer::Reduction



28
29
30
# File 'lib/rack/reducer.rb', line 28

def self.create(dataset, *filters)
  Reduction.new(dataset, *filters)
end

.new(app, options = {}) ⇒ Object

Deprecated.

Rack::Reducer.new will become an alias of ::create in v2.0. To mount middleware that will still work in 2.0, write “use Rack::Reducer::Middleware” instead of “use Rack::Reducer”

Mount Rack::Reducer as middleware



55
56
57
58
# File 'lib/rack/reducer.rb', line 55

def self.new(app, options = {})
  warn "#{caller(1..1).first}}\n#{Warnings[:new]}"
  Middleware.new(app, options)
end

Instance Method Details

#reduces(dataset, filters:) ⇒ Object

Deprecated.

Rack::Reducer’s mixin-style is deprecated and may be removed in 2.0. To keep using Rack::Reducer in your models, create a Reducer constant.

class MyModel < ActiveRecord::Base
  MyReducer = Rack::Reducer.create(dataset, *filter_functions)
end
MyModel::MyReducer.call(params)

Extend Rack::Reducer to get reduce and reduces as class-methods

Examples:

Make an “Artists” model reducible

class Artist < SomeORM::Model
  extend Rack::Reducer
  reduces self.all, filters: [
    lambda { |name:| where(name: name) },
    lambda { |genre:| where(genre: genre) },
  ]
end
Artist.reduce(params)


79
80
81
82
83
84
85
# File 'lib/rack/reducer.rb', line 79

def reduces(dataset, filters:)
  warn "#{caller(1..1).first}}\n#{Warnings[:reduces]}"
  reducer = Reduction.new(dataset, *filters)
  define_singleton_method :reduce do |params|
    reducer.apply(params)
  end
end