óCoffeeScript Cookbook

Chaining Calls to an Object

Problem

You want to call multiple methods on a single object without having to reference that object each time.

Solution

Return the this (i.e. @) object after every chained method.

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 }

Discussion

The jQuery library uses a similar approach by returning a selector object from every relevant method, modifying it as subsequent methods tweak the selection:

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

For your own objects, a touch of metaprogramming can automate the setup process and explicitly state the purpose of returning this.

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, cream: false }

earlgrey.sugar true

earlgrey.sugar() # => true