Ruby Methods and Optional Parameters

A method with an optional parameter


def some_func(variable = nil)
...
end

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)
...

Ruby method with optional options and &block parameter

Yes, it is possible.

When mixing different kinds of parameters, they have to be included in the method definition in a specific order:

  1. Positional parameters (required and optional) and a single splat parameter, in any order;
  2. Keyword parameters (required and optional), in any order;
  3. Double splat parameter;
  4. Block parameter (prefixed with &);

The order above is somewhat flexible. We could define a method and begin the parameter list with a single splat argument, then a couple of optional positional arguments, and so on. Even though Ruby allows that, it's usually a very bad practice as the code would be hard to read and even harder to debug. It's usually best to use the following order:

  1. Required positional parameters;
  2. Optional positional parameters (with default values);
  3. Single splat parameter;
  4. Keyword parameters (required and optional, their order is irrelevant);
  5. Double splat parameter;
  6. Explicit block parameter (prefixed with &).

Example:

def meditate cushion, meditation="kinhin", *room_items, time: , posture: "kekkafuza", **periods, &b
puts "We are practicing #{meditation}, for #{time} minutes, in the #{posture} posture (ouch, my knees!)."
puts "Room items: #{room_items}"
puts "Periods: #{periods}"
b.call # Run the proc received through the &b parameter
end

meditate("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon" ) { puts "Hello from inside the block" }

# Output:
We are practicing zazen, for 40 minutes, in the kekkafuza posture (ouch, my knees!).
Room items: ["zabuton", "incense"]
Periods: {:period1=>"morning", :period2=>"afternoon"}
Hello from inside the block

Notice that when calling the method, we have:

  • Provided the cushion mandatory positional argument;
  • Overwritten the default value of the meditation optional positional argument;
  • Passed a couple of extra positional arguments (zabuton and incense) through the *room_items parameter;
  • Provided the time mandatory keyword argument;
  • Omitted the posture optional keyword argument;
  • Passed a couple of extra keyword arguments (period1: "morning", period2: "afternoon") through the **periods parameter;
  • Passed the block { puts "Hello from inside the block" } through the &b parameter;

Please note the example above servers only to illustrate the possibility of mixing different types of parameters. Building a method like this in real code would be a bad practice. If a method needs that many arguments, it's probably best to split it into smaller methods. If it's absolutely necessary to pass that much data to a single method, we should probably create a class to store the data in a more organized way, then pass an instance of that class to the method as a single argument.

How to pass an optional method parameter as string in Ruby

It doesn't work because you are sending symbol (:something) instead of string key ('something'). They are different objects.

Change:

method("param1", "param2", :something => true)

to

method("param1", "param2", 'something' => true)

or handle in method by if options[:something]

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.

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.

Methods with optional and keyword arguments

If you want this exact signature, you should probably use double-splat for b parameter:

def test(a, c: 1, **b)
[a, b, c]
end
test 1, {hello: :world}
#⇒ [1, {hello: :word}, 1]

There are issues distinguishing named keyword parameters and the hash itself when the latter is passed immediately before named keywords.

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.

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.



Related Topics



Leave a reply



Submit