Skip to content

Instantly share code, notes, and snippets.

@datashaman
Last active January 3, 2016 20:29
Show Gist options
  • Save datashaman/8515466 to your computer and use it in GitHub Desktop.
Save datashaman/8515466 to your computer and use it in GitHub Desktop.
Cumulative object for filters

Cumulative object, useful for creating filters. It's closest to a Reader / Environment monad.

Every time you call it with arguments, it merges them into a running context, which it uses to create the next filter which is returned. You can create graphs of filters, deriving from a common point.

If the argument is callable, call it to get the new properties to merge. This allows you to dynamically create the properties on the fly.

When you want to get the current context, call the filter without arguments, which is a signal for the filter to return the internal context object.

This means you can easily merge two filters together, since filters are callable and produce their context if called without arguments.

You can create objects in a remarkably literate style.

Look at definition.coffee for its definition. Look at usage.coffee for examples of its usage.

_ = require('lodash')
filter = (context={}) ->
_.merge (extra) ->
if extra?
if typeof extra == 'function'
extra = extra()
filter(_.merge(_.cloneDeep(context), extra))
else
context
, context: context
filter = require('./definition.coffee')
formats =
html: 'text/html'
json: 'application/json'
# Shortcut filter creation
method = (method) ->
filter method: method.toUpperCase()
format = (format) ->
filter accepts: formats[format]
route = (name) ->
filter route: name: name
# home becomes an object which is a
# combination of method('get') and route('home')
get = method 'get'
home = get route 'home'
# this is fundamentally the same thing
home = get { route: { name: name } }
# which is the same as this
home = home { method: 'GET' }
html = format 'html'
json = format 'json'
home_api = home json
# home_api() will return:
# {
# route: { name: 'home' },
# method: 'GET',
# accepts: 'application/json'
# }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment