A method with an optional parameter
def some_func(variable = nil)
...
end
Order of optional parameters in initializer
If you define optional parameters before AND after mandatory parameters, in some cases it will be impossible to decide how a goven list or arguments should map to the defined parameters.
In your case, when defining this method:
class A
def initialize(a = "default val", b, c = [])
#...
end
end
How would you handle this when giving two arguments,. i.e.
A.new 'hello', 'world'
You could then assign
a = 'hello'
b = 'world'
c = []
but you could equally set
a = 'default val'
b = 'hello'
c = 'world'
Given this unambiguity, Ruby rejects those constructs. You thus have to define all optional parameters either at the front or the back of your parameter list, while it is commonly accepted standard to define optional arguments only at the end.
If you want to be more specific about which arguments should be set with a large number of optional parameters, you can also use keyword arguments. Since you have to specify the name of the arguments when calling the method here, the order of mandatory and optional keyword arguments doesn't matter.
ArgumentError with optional parameters
In Ruby < 3.0, if the last argument is a hash, and the method being called accepts keyword arguments, then it is always converted to keyword arguments.
Ruby 3.0 fixes this.
You should upgrade to Ruby 3.0 if you can, or else think of a different API.
Ruby optional parameters
This isn't possible with ruby currently. You can't pass 'empty' attributes to methods. The closest you can get is to pass nil:
ldap_get(base_dn, filter, nil, X)
However, this will set the scope to nil, not LDAP::LDAP_SCOPE_SUBTREE.
What you can do is set the default value within your method:
def ldap_get(base_dn, filter, scope = nil, attrs = nil)
scope ||= LDAP::LDAP_SCOPE_SUBTREE
... do something ...
end
Now if you call the method as above, the behaviour will be as you expect.
Ruby Methods and Optional parameters
The way optional arguments work in ruby is that you specify an equal sign, and if no argument is passed then what you specified is used. So, if no second argument is passed in the second example, then
{age: 27, weight: 160, city: "New York"}
is used. If you do use the hash syntax after the first argument, then that exact hash is passed.
The best you can do is
def my_info2(name, options = {})
options = {age: 27, weight: 160, city: "New York"}.merge(options)
...
Best way to send() optional parameter in Rails
If you're using Ruby 2.2.0 or later you can call #itself
on any object and get that object. So in your example you can do
def foo param_1, param_2 = :itself
object.send(param_1).send(param_2)
end
And it will be the same as
def foo param_1, param_2 = nil
thing = object.send(param_1)
if param_2
thing.send(param_2)
else
thing
end
end
I also second Surya's advice to always use #public_send
instead.
Rails optional argument
It's as simple as this:
class Person
attr_accessor :name, :age
def initialize(name = '', age = 0)
self.name = name
self.age = age
end
end
Person.new('Ivan', 20)
Person.new('Ivan')
However, if you want to pass only age, the call would look pretty ugly, because you have to supply blank string for name anyway:
Person.new('', 20)
To avoid this, there's an idiomatic way in Ruby world: options parameter.
class Person
attr_accessor :name, :age
def initialize(options = {})
self.name = options[:name] || ''
self.age = options[:age] || 0
end
end
Person.new(name: 'Ivan', age: 20)
Person.new(age: 20)
Person.new(name: 'Ivan')
You can put some required parameters first, and shove all the optional ones into options
.
Edit
It seems that Ruby 2.0 will support real named arguments.
def example(foo: 0, bar: 1, grill: "pork chops")
puts "foo is #{foo}, bar is #{bar}, and grill is #{grill}"
end
# Note that -foo is omitted and -grill precedes -bar
example(grill: "lamb kebab", bar: 3.14)
Ruby's Faraday - Send optional parameters in get method
You don't have to concatenate params with the url on your own. Faraday can accept a hash of params (or nil). You can pass them to the get method like so:
response = connection.get(customer_url, params)
Have into the "GET, HEAD, DELETE, TRACE" section of the documentation for more examples.
Side note: you don't event have to concatenate url and the path. You can pass them as separate arguments.
Ruby Object Initialize with Optional Arguments
If you're going to do that you need to accept not an array of arguments (varargs style) like you've specified, but either an options hash or the new keyword-args style option.
The classic approach:
def initialize(attributes = nil)
attributes and attributes.each do |k,v|
instance_variable_set("@#{k}", v) unless v.nil?
end
end
The new keyword-arguments approach:
def initialize(**options)
options.each do |k,v|
instance_variable_set("@#{k}", v) unless v.nil?
end
end
You can also subclass OpenStruct to get behaviour like this for free.
Keep in mind there's a new option style that might be a good mix of both these approaches:
def initialize(sid: '123', token: '...', ...)
@sid = sid
@token = token
# ...
end
You can specify defaults for the named keyword arguments.
Related Topics
Escape Single Quote in Xpath with Nokogiri
How to Pass Arguments to Define_Method
Why Can't I Use an Integer as a Key Using the New Ruby 1.9.2 Hash Syntax
How Does Require Rubygems Help Find Rubygem Files
Activerecord::Connectiontimeouterror
How to Know If Today's Date Is in a Date Range
Rubygems, Bundler and Rvm Confusion
What's the Best Way to Unit Test Protected & Private Methods in Ruby
Replace Words in a String - Ruby
Add Timestamps to an Existing Table
Descending Sort by Value of a Hash in Ruby
How to Make Rails 3.1 Use SASS (Over SCSS) as the Default