Keyword Arguments
Using arbitrary keyword arguments with splat operator
Section titled “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 argsend
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 foundUsing 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: fooThis is generally used when you need to manipulate incoming arguments, and pass them to an underlying method:
def inner(foo:, bar:) puts foo, barend
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 barUsing keyword arguments
Section titled “Using keyword arguments”You define a keyword argument in a method by specifying the name in the method definition:
def say(message: "Hello World") puts messageend
say# => "Hello World"
say message: "Today is Monday"# => "Today is Monday"You can define multiple keyword arguments, the definition order is irrelevant:
def say(message: "Hello World", before: "<p>", after: "</p>") puts "#{before}#{message}#{after}"end
say# => "<p>Hello World</p>"
say message: "Today is Monday"# => "<p>Today is Monday</p>"
say after: "</p><hr>", message: "Today is Monday"# => "<p>Today is Monday</p><hr>"Keyword arguments can be mixed with positional arguments:
def say(message, before: "<p>", after: "</p>") puts "#{before}#{message}#{after}"end
say "Hello World", before: "<span>", after: "</span>"# => "<span>Hello World</span>"Mixing keyword argument with positional argument was a very common approach before Ruby 2.1, because it was not possible to define required keyword arguments.
Moreover, in Ruby < 2.0, it was very common to add an Hash at the end of a method definition to use for optional arguments. The syntax is very similar to keyword arguments, to the point where optional arguments via Hash are compatible with Ruby 2 keyword arguments.
def say(message, options = {}) before = option.fetch(:before, "<p>") after = option.fetch(:after, "</p>") puts "#{before}#{message}#{after}"end
# The method call is syntactically equivalent to the keyword argument onesay "Hello World", before: "<span>", after: "</span>"# => "<span>Hello World</span>"Note that trying to pass a not-defined keyword argument will result in an error:
def say(message: "Hello World") puts messageend
say foo: "Hello"# => ArgumentError: unknown keyword: fooRequired keyword arguments
Section titled “Required keyword arguments”Required keyword arguments were introduced in Ruby 2.1, as an improvement to keyword arguments.
To define a keyword argument as required, simply declare the argument without a default value.
def say(message:) puts messageend
say# => ArgumentError: missing keyword: message
say message: "Hello World"# => "Hello World"You can also mix required and non-required keyword arguments:
def say(before: "<p>", message:, after: "</p>") puts "#{before}#{message}#{after}"end
say# => ArgumentError: missing keyword: message
say message: "Hello World"# => "<p>Hello World</p>"
say message: "Hello World", before: "<span>", after: "</span>"# => "<span>Hello World</span>"Remarks
Section titled “Remarks”Keyword arguments were introduced in Ruby 2.0, and improved in Ruby 2.1 with the addition of required keyword arguments.
A simple method with a keyword argument looks like the following one:
def say(message: "Hello World") puts messageend
say# => "Hello World"
say message: "Today is Monday"# => "Today is Monday"As a reminder, the same method without keyword argument would have been:
def say(message = "Hello World") puts messageend
say# => "Hello World"
say "Today is Monday"# => "Today is Monday"You can simulate keyword argument in previous Ruby versions using a Hash parameter. This is still a very common practice, especially in libraries that provides compatibility with pre-2.0 Ruby versions:
def say(options = {}) message = options.fetch(:message, "Hello World") putsend
say# => "Hello World"
say message: "Today is Monday"# => "Today is Monday"