Posted about 1 year ago. Visible to the public. Linked content.

Using the Ruby block shortcut with arguments

Ruby has this handy block shortcut map(&:to_i) for map { |x| x.to_i }. However, it is limited to argument-less method invocations.

To call a method with an argument, you usually need to use the full block form. A common case is retrieving values from a list of hashes (imagine using a JSON API):

users = [ { name: 'Dominik', color: 'blue' }, { name: 'Stefan', color: 'red'} ] names = users.collect do |user| user['name'] end

But with a little extension, you can do better.

Block shortcut with arguments

By defining Symbol#call, you can start passing arguments to the short block form.

class Symbol def call(*args, &block) ->(caller, *rest) { caller.send self, *rest, *args, &block } end end

As an intermediate result, you can now do this:

users.collect &:[].call(:name)

This looks really awkward, and it is mostly because of the [] used in the example above. Other method invocations would already be quite readable.

In order to improve legibility, we use two more tools:

  • the Array#dig and Hash#dig methods introduced in Ruby 2.3, using them as an alias for #[]
  • the syntactic sugar .() that invokes the #call method on the object


Now we can do this:

users = [ { name: 'Dominik', color: 'blue' }, { name: 'Stefan', color: 'red'} ] names = users.collect &:dig.(:name)

Note that this example is very well suited for working with JSON, where you're usually collecting values at a certain path through the JSON data structure. This is what #dig was designed for. Example: projects.collect &:dig.(:company, :tags, 0, :name) will call project[:company][:tags][0][:name] for each project and collect the results.

Also note that you can go a little bit more explicit by calling the new method Symbol#with. Usage would then be: users.collect &:dig.with(:name).

Credits to the linked StackOverflow question.

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Owner of this card:

Dominik Schöler
Last edit:
about 1 year ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more