lib/rack/reducer.rb in rack-reducer-1.0.1 vs lib/rack/reducer.rb in rack-reducer-1.1.0

- old
+ new

@@ -1,56 +1,87 @@ +# frozen_string_literal: true + require_relative 'reducer/reduction' require_relative 'reducer/middleware' +require_relative 'reducer/warnings' module Rack - # Use request params to apply filters to a dataset + # Declaratively filter data via URL params, in any Rack app. module Reducer - # Filter a dataset + # Create a Reduction object 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 + # @return Rack::Reducer::Reduction + # @example 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 + def self.create(dataset, *filters) + Reduction.new(dataset, *filters) + end + + # 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. + # # @param params [Hash] Rack-compatible URL params # @param dataset [Object] A dataset, e.g. one of your App's models # @param filters [Array<Proc>] An array of lambdas with keyword arguments # @example Call Rack::Reducer as a function in a Sinatra app - # ArtistReducer = { - # dataset: Artist, - # filters: [ + # get '/artists' do + # @artists = Rack::Reducer.call(params, dataset: Artist.all, filters: [ # lambda { |name:| where(name: name) }, # lambda { |genre:| where(genre: genre) }, - # ] - # } - # get '/artists' do - # @artists = Rack::Reducer.call(params, ArtistReducer) + # ]) # end def self.call(params, dataset:, filters:) - Reduction.new( - params: params, - filters: filters, - dataset: dataset - ).reduce + Reduction.new(dataset, *filters).apply(params) end # Mount Rack::Reducer as middleware + # @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" def self.new(app, options = {}) + warn "#{caller(1..1).first}}\n#{Warnings[:new]}" Middleware.new(app, options) end # Extend Rack::Reducer to get +reduce+ and +reduces+ as class-methods + # # @example 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) + # + # @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) def reduces(dataset, filters:) + warn "#{caller(1..1).first}}\n#{Warnings[:reduces]}" + reducer = Reduction.new(dataset, *filters) define_singleton_method :reduce do |params| - Reduction.new( - params: params, - filters: filters, - dataset: dataset, - ).reduce + reducer.apply(params) end end end end