Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Chained calls to CoffeeScript objects


May 09, 2021 CoffeeScript


Table of contents


The chain call of the object

Problem

You want to call multiple methods on an object, but you don't want to reference the object every time.

Solution

Returns the thiss object after each chain call

class CoffeeCup
    constructor:  ->
        @properties=
            strength: 'medium'
            cream: false
            sugar: false
    strength: (newStrength) ->
        @properties.strength = newStrength
        this
    cream: (newCream) ->
        @properties.cream = newCream
        this
    sugar: (newSugar) ->
        @properties.sugar = newSugar
        this

morningCup = new CoffeeCup()

morningCup.properties # => { strength: 'medium', cream: false, sugar: false }

eveningCup = new CoffeeCup().strength('dark').cream(true).sugar(true)

eveningCup.properties # => { strength: 'dark', cream: true, sugar: true }

Discuss

The jQuery library uses a similar method to return the selector object from each similar method, and in subsequent methods modifies the object by adjusting the selection range:

$('p').filter('.topic').first()

For our own objects, a little metaprogramming can automatically set up the process and clearly state the intention to return the thisis.

addChainedAttributeAccessor = (obj, propertyAttr, attr) ->
    obj[attr] = (newValues...) ->
        if newValues.length == 0
            obj[propertyAttr][attr]
        else
            obj[propertyAttr][attr] = newValues[0]
            obj

class TeaCup
    constructor:  ->
        @properties=
            size: 'medium'
            type: 'black'
            sugar: false
            cream: false
        addChainedAttributeAccessor(this, 'properties', attr) for attr of @properties

earlgrey = new TeaCup().size('small').type('Earl Grey').sugar('false')

earlgrey.properties # => { size: 'small', type: 'Earl Grey', sugar: false }

earlgrey.sugar true

earlgrey.sugar() # => true