Ruby Language Using arbitrary keyword arguments with splat operator


Example

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

def say(**args)
  puts args
end

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"
end

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}"
end

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

args = { message: "Hello World", foo: "1" }
say(**args)
# => 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
end

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

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