liveBook · Manning

Method chaining

As explained in The Well-Grounded Rubyist, Fourth Edition

A method chain is a sequence in which the result of one method call becomes the receiver of a subsequent method call.

A collection pipeline

Given `animals = %w(Jaguar Turtle Lion Antelope)`, `animals.select { |n| n[0] < 'M' }.map(&:upcase).join(', ')` produces `"JAGUAR, LION, ANTELOPE"`. Each call works on the preceding call’s result: select names, uppercase them, then join them. section 10.11

A chain makes a sequence of transformations read from left to right. In `"joe".upcase.reverse`, `"joe"` receives `upcase`; its result, `"JOE"`, receives `reverse`. The intermediate value is not printed or assigned. Chaining works smoothly here because both calls return strings and neither has a side effect. section 16.3.2

Check what each link returns before extending a chain:

  • Collection chains can allocate intermediate objects. The animal pipeline creates arrays from `select` and `map`, then a string from `join`. Enumerators can reduce intermediate-object creation in some cases, but do not eliminate every cost. section 10.11
  • Many iterators, including `each`, `map`, and `select`, return an enumerator when called without a block. That enumerator can receive the next method call. section 10.9.3
  • A mutating method may interrupt the chain: `gsub!` returns `nil` when it makes no substitution, so a following string method would be called on `nil`. Use a nonmutating alternative such as `gsub`, or separate the calls when that return value matters. section 13.2.1

For a block-shaped step, `then` (also called `yield_self`) passes the receiver into the block and returns the block’s result, ready for another call. `tap` also passes in the receiver but returns that receiver instead. Choose between them according to which value the next link needs. `itself` simply returns its receiver; for example, `group_by(&:itself)` groups equal values by those values. section 16.3.3

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Works through return values, collection allocation, and failure when a mutating method returns nil; stops short of exhaustive API guidance.
Examples
Uses animal-name filtering and uppercasing, string reversal, and a failed gsub! chain to make successive receivers visible.
What it assumes
Assumes familiarity with Ruby method calls, blocks, strings, and collections while explaining how one call’s result becomes the next receiver.
What you can do after
Practice/perform Ruby method chaining while checking intermediate types, return values, allocation, and possible nil results.
How it connects
Connects Enumerable, Enumerator, side effects, referential transparency, and Kernel#then through the values passed between calls.

Also explained in

Compare how 3 books explain method chaining →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.