Ruby Language Keyword Arguments Using arbitrary keyword arguments with splat operator


You can define a method to accept an arbitrary number of keyword arguments using the double splat (**) operator:

def say(**args)
  puts args

say foo: "1", bar: "2"
# {:foo=>"1", :bar=>"2"}

The arguments are captured in a Hash. You can manipulate the Hash, for example to extract the desired arguments.

def say(**args)
  puts args[:message] || "Message not found"

say foo: "1", bar: "2", message: "Hello World"
# Hello World

say foo: "1", bar: "2"
# Message not found

Using a the splat operator with keyword arguments will prevent keyword argument validation, the method will never raise an ArgumentError in case of unknown keyword.

As for the standard splat operator, you can re-convert a Hash into keyword arguments for a method:

def say(message: nil, before: "<p>", after: "</p>")
  puts "#{before}#{message}#{after}"

args = { message: "Hello World", after: "</p><hr>" }
# <p>Hello World</p><hr>

args = { message: "Hello World", foo: "1" }
# => ArgumentError: unknown keyword: foo

This is generally used when you need to manipulate incoming arguments, and pass them to an underlying method:

def inner(foo:, bar:)
  puts foo, bar

def outer(something, foo: nil, bar: nil, baz: nil)
  puts something
  params = {}
  params[:foo] = foo || "Default foo"
  params[:bar] = bar || "Default bar"

outer "Hello:", foo: "Custom foo"
# Hello:
# Custom foo
# Default bar