Can I have required named parameters in Ruby 2.x?
There is no specific way in Ruby 2.0.0, but you can do it Ruby 2.1.0, with syntax like def foo(a:, b:) ...
In Ruby 2.0.x, you can enforce it by placing any expression raising an exception, e.g.:
def say(greeting: raise "greeting is required")
# ...
end
If you plan on doing this a lot (and can't use Ruby 2.1+), you could use a helper method like:
def required
method = caller_locations(1,1)[0].label
raise ArgumentError,
"A required keyword argument was not specified when calling '#{method}'"
end
def say(greeting: required)
# ...
end
say # => A required keyword argument was not specified when calling 'say'
At the current moment (Ruby 2.0.0-preview1) you could use the following method signature:
def say(greeting: greeting_to_say)
puts greeting
end
The greeting_to_say
is just a placeholder which won't be evaluated if you supply an argument to the named parameter. If you do not pass it in (calling just say()
), ruby will raise the error:
NameError: undefined local variable or method `greeting_to_say' for (your scope)
However, that variable is not bound to anything, and as far as I can tell, cannot be referenced from inside of your method. You would still use greeting
as the local variable to reference what was passed in for the named parameter.
If you were actually going to do this, I would recommend using def say(greeting: greeting)
so that the error message would reference the name you are giving to your parameter. I only chose different ones in the example above to illustrate what ruby will use in the error message you get for not supplying an argument to the required named parameter.
Tangentially, if you call say('hi')
ruby will raise ArgumentError: wrong number of arguments (1 for 0)
which I think is a little confusing, but it's only preview1.
Combining the solutions from @awendt and @Adam,
def say(greeting: ->{ raise ArgumentError.new("greeting is required") }.call)
puts greeting
end
You can DRY this up with something like:
def required(arg)
raise ArgumentError.new("required #{arg}")
end
def say(greeting: required('greeting'))
puts greeting
end
And combining that with @Marc-Andre's solution: https://gist.github.com/rdp/5390849
In Ruby 2.3, I can do
def say(greeting:)
puts greeting
end
Then use it with...
say(greeting: "hello there")
How about:
def say(greeting: nil)
greeting or raise ArgumentError
puts greeting
end
say # => raises ArgumentError
say(greeting: 'howdy') # => puts 'howdy'
Other than that, it is going to be difficult. According to this site, keyword arguments “are named parameters that have default values.“