Keyword Arguments in Ruby

sheldon

The ‘normal’ way of passing arguments to a method or class in Ruby can be illustrated as follows:

def hello(message, receiver)
  "#{message}, #{receiver}!"
end

hello('greetings', 'earthling')
# => greetings, earthling!

Positional arguments work fine in most cases, but have a look at this:

class Airport
  DEFAULT = 20
  def initialize(capacity = DEFAULT, weather = :stormy)
    @capacity = capacity
    @weather = weather
  end
end

Now, when I initialize a new Airport, I can write :

airport = Airport.new
# => <Airport:0x007fc3190a7c40 @capacity=20, @weather="stormy">

But what happens when I want to pass different weather? The only way of doing that would be:

airport = Airport.new(Airport::DEFAULT, :stormy)
# => <Airport:0x007fc3190a7c40 @capacity=20, @weather="rainy">

And that is a needless passing of a value that is defaulted any way, and we coders are lazy, right? Since Ruby 2.0 it is possible to use named arguments, which help a coder to be even more lazy. Have a look at this:

class Airport
  DEFAULT = 20
  def initialize(capacity: DEFAULT, weather: :stormy)
    @capacity = capacity
    @weather = weather
  end
end

airport = Airport.new(weather: :rainy)
# => <Airport:0x007fc3190a7c40 @capacity=20, @weather="rainy">

Using keyword arguments (or named attributes), the order in which arguments are passed doesn’t matter:

airport = Airport.new(weather: :sunny, capacity: 50)
# => <Airport:0x007fc319047b10 @capacity=50, @weather=:sunny>

The flexibility and code clarity of keyword arguments is, of course, a trade-off with the more concise code of the ‘normal’ way of passing arguments.

Further reading on keyword arguments

Written on October 20, 2015