Using call in Ruby classes

Recently looking at the source for jbuilder I noticed the curious syntax:


json.(var, :sym1, :sym2)
      

Later I discovered that it’s some syntastic sugar for call. You may be familiar with this method from using a Proc or lambda, or even passing blocks around like so:


proc { 'Hello, world!' }.call #=> "Hello, world!"
-> { 'Hello, world!' }.call   #=> "Hello, world!"

def some_method(&block)
  @block = block
end

some_method do
  'Hello, world!'
end

@block.call #=> "Hello, world!"
      

So we know that all of these are forms of Proc in action. It turns out you can do more with call outside of the realm of Proc.

jbuilder just happens to use call as a short form of it’s extract! method, allowing you to pass an object to it listing attributes (or methods) to “extract” for display. I’ll demonstrate:


class Person
  attr_accessor :name, :age, :sex

  def initialize(name, age, sex)
    self.name = name
    self.age  = age
    self.sex  = sex
  end

  def call(*attributes)
    attributes.map do |attribute|
      self.method(attribute).call
    end
  end
end

person = Person.new('James', 21, 'male')
person.(:name, :sex) #=> ["James", "male"]
      

In this example I used the alternative syntax for call, rather than person.call(...).

So what is this good for? A good example of a project that has heavy use of call in classes is Rack. You’ll find in a lot of it’s classes that it uses call as kind of a central API.

Shout out to my friend Jeremy for telling me a little more about this stuff when I first ran into it.