Ruby Keyword Arguments

Nicholas Cancelliere
ozmox
Published in
2 min readMay 9, 2017

--

A new feature introduced in Ruby 2.0, keyword arguments makes having to pass an options hash into a method a thing of the past.

Before Ruby 2.0 you would commonly see a pattern like this:

def say(options = {})
message = options.fetch(:hello, 'Hello world (default)!')
puts message
end

In Ruby 2.0 however you can simply express this as:

def say(hello: 'Hello world!')
puts message
end

Another, less used but still cool, use is to define keyword arguments for a block. You can of course also do this with a hash pre Ruby 2.0, but now with keyword arguments there is no reason to.

define_method(:say) do | hello: 'Hello world!' |
puts hello
end

Required Keywords

Ruby 2.1 and later supports the ability to require arguments by simply providing a colon (and no default value). This is not be be confused with nil which will set the default value to nil! When a required keyword is not provided then an ArgumentError is raised.

def say(hello:)
puts hello
end
$ say
=> ArgumentError: missing keyword: hello
$ say(hello: 'Welcome readers!')
=> Welcome readers!

Connascence and Keyword Arguments

Connascence of Position is the idea in computer science where the order (or position) or something creates dependency. This is to say when you use positional parameters, the caller and callee both have to agree on what the positions mean. This means changing your method later can be more difficult since there is dependency on the order — all the callers would have to be updated too.

Take for example this method:

link_to(name: 'Apple', url: 'http://www.apple.com', target: 'blank')

With keyword arguments you could also call it like so and it’d still be valid:

link_to(url: 'http://www.apple.com', name: 'Apple', target: 'blank')

However if you used positional parameters, then you could only call it in a specific order as defined by the method:

link_to('Apple', 'http://www.apple.com', 'blank')

Sometimes it is ok to use positional arguments, if they are obvious and the method is likely never to be changed and adding new parameters onto the end is not going to be a big deal. But consider this:

calculate_total(85, 12, 5)

Do you know what the above method parameters are for? Not without looking at the method definition. Now what if you instead saw this:

calculate_total(subtotal: 85, tax: 12, discount: 5)

This method communicates better and you don’t have to peek into the implementation to understand what is needed to call it.

In Summary

There are trade-offs to everything, but for most methods keyword arguments are a better choice than positional ones. They reduce the effort needed in parsing option hashes and manually checking for required argument (keys). They help clearly communicate what a method call requires, without the need to examine its implementation. Lastly they reduce connascence and allow code to be refactored more easily. Of course it doesn’t mean you should never use positional arguments.

--

--

Software engineering manager living in ATX / Foodie / Gamer / Explorer