Posted 11 days ago. Visible to the public.

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):

Copy
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.

Copy
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:

Copy
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

Usage

Now we can do this:

Copy
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.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Author of this card:

Avatar
Dominik Schöler
Last edit:
5 days 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