Skip to content

Methods

Last updated on June 30th, 2024 at 08:12 pm

Table of Contents

Methods

Basic Method Definition

A method is created using the def statement and terminated using the end statement. Between the def and the end statements, the world is your oyster.

Method Naming

Methods should be named in snake_case. Refer to the Ruby Style Guide for more information.

Passing Arguments

As with just about any other programming language, you will want to be able to pass your methods arguments that they can operate on. Normally, arguments are passed by position. Although the parenthesis are not required, it is considered desirable styling to include them.

This operates very much as you would expect. When you invoke the method, you would place the arguments in the sequence used when the method was defined, separating the values by a comma.

Calling the method above using the statement my_method 12, 14, the value 12 is assigned to the variable height and the value 14 is assigned to the variable weight. You may notice that the example I provided didn’t surround the arguments with parenthesis. This is because parenthesis are optional when defining and invoking methods. However – be advised that there are some situations where Ruby can get confused if you don’t wrap your arguments in parenthesis, for example when using the ternary operator. As well, parenthesis are also required if you want to chain methods.

Because Ruby is not a strongly typed language, there are no restrictions or controls on what types of values you can pass. This means that if you make a mistake and pass the wrong object type, i.e. a string where an integer is expected, you won’t find out until you try to use the value when the method is invoked during runtime.

Default Values for Arguments

Ruby gives you the option of providing default values on arguments, but with some restrictions. In a nutshell, if you provide default values, you have to put these arguments at the end of the of the def statement, as with the following example.

You cannot, however, have something like the following:

Thinking about this, it is pretty clear that when the method is invoked, the interpreter would never know how to assign arguments that are passed. Additionally, once you invoke the method and start taking advantage of the default argument values, you cannot selectively determine which arguments get defaults and which don’t. That is, once a default argument is used, all remaining arguments need to use defaults as well.

Let’s have a look at what this means using the first example of my_method. I can invoke my_method with the statement my_method(1,2 3) or my_method(1, 2), but I cannot use something like my_method(1, , 3).

Named Arguments

Ruby also allows you to name your arguments and then pass your arguments using their names.

You will notice that the first argument wasn’t named, which means that naming arguments is similar to giving arguments defaults. Not all arguments have to be named, but once you start, all remaining arguments have to be named.

You can also give named arguments default values.

Passing a Variable Number of Arguments

Ruby also has the interesting ability to pass a method a variable number of arguments. By preceding the last argument with an asterisk, those arguments will be dealt with as an Array.

Although Ruby will allow you to define an argument with a default value, the default can only be taken if that given argument and all following it are missing.

That is, you cannot do something like my_method(1,2, ,4, 5,6,7,8,9) to try and use the default value for the third argument and then pass values for everything_else.

Passing Methods as Arguments

Ruby allows you to pass a method as an argument. This is as simple as passing the name of the method in the argument list and executing it in the called method.

or, alternatively

Passing Blocks as Arguments

Additionally, you are able to pass a ruby code block as the last argument. The block can either be declared explicitly with def perform_operation(a, b, &block) or implicitly with def perform_operation(a, b). If a block is explicitly passed, it is converted into a Proc, which can then be called by name. Obviously, when the block is called, it must expect the same number of parameters as you pass to it on the call.

For a thorough discussion of methods and arguments, I suggest you invest in Jeremy Evans’ book, Polished Ruby Programming and have a look at Chapter 4, “Methods and Their Arguments”.

Returning Values from Methods

Although a method can be written that performs an action that doesn’t return any value, that is somewhat rare. Normally, we want a method to return a value. In Ruby, you have a few options. First, you can use the return statement anywhere in the method’s code block. This will halt the execution of the method and, optionally, return values.

Additionally, Ruby automatically considers the last statement of a method as a return value. You may add the return statement if you wish, but it is not required.

Endless Methods

Ruby 3.0 introduced the concept of Endless Methods. These are basically one-line methods.

Method Visibility

There are three levels of visibility within Ruby – public, protected and private. Whether a method should be private, public or protected depends more upon your personal opinion or company policy than anything else – see Noel Rappin’s blog post for an interesting perspective on when a method should be public. It is important to know that regardless of how you set the visibility on an object, this can be overridden by simply using the send method.

Public

Public visibility is the default value for all methods. If a method is public it can be accessed by any user of the object created from the class.

Protected

If a method is declared as protected, it can only be called from a subclass of the receiver or the receiver must be a subclass of the sender. Otherwise a NoMethodError will be raised.

Private

If a method is declared as private, it is only available from within the Class and cannot be used via the object created from the class.

Declaring Visibility

There are three ways to declare method visibility, normal, postfactum and inline.

Class Methods

A class without methods is pretty much useless. Methods are code within a class that performs a function related to the class. NOTE – You can define methods in a class that have absolutely nothing to do with the class, but that would normally be considered a code smell. Defining methods within a class is accomplished using the def statement. The def is followed by the name of the method, typically in snake_case and terminated with an end statement. Method names should always begin with a lower case letter and use an underscore (_) to separate words. The Ruby style guide suggests two space indentation.

Methods can take any number of parameters. Parameters can take on default values by assigning them on the def statement. Parameters with default values must always be at the end of the parameter list. You can also call the method using the parameters in any order, if you use their names.

Methods ending in ?, ! and =

The Ruby style guide suggests that methods which don’t modify anything and return a true / false value end with a question mark (?).

If a method will modify the object that is calling it, it should end in an exclamation point (!).

If the method is a setter method for a class variable (which we will cover later in this guide), then it must end with an equals sign (=).

Calling a Method

There are a few different ways to call methods in Ruby. The first, and most common mechanism is to use the method name, followed by a left parenthesis “(“, followed by the arguments, and closing with a right parenthesis “)”.

The wrapping parenthesis are actually optional, but desirable. The method above can be rewritten to:

Ruby is even intelligent enough to handle conditional method calls, such as:

This is not advisable and things break down if you want to chain methods. In this case, the parenthesis are necessary.

Using send

Another mechanism to make method calls is the send statement. send is a method that every object responds to and it takes an argument which is the name of the method to be called, followed by the arguments to be passed to the method. The name of the method can be a symbol or a string.

One very important thing to note with send is that it bypasses privacy restrictions on methods. That is, I can issue a send against a method that is marked as private and it will work fine.

Using call

Ruby also allows you to define a method and assign it to a variable, which can later be executed using the call method. This would most commonly be used for Procs and Lambdas.

Differences between send and call

Context:

  • send is used for calling methods on objects dynamically.
  • call is used to execute Proc or lambda objects.

Target:

  • send targets methods defined on an object.
  • call targets Proc or lambda objects.

Method Visibility:

  • send can invoke private and protected methods.
  • call has no concept of method visibility since it’s used with Proc or lambda.

Syntax:

  • send: object.send(:method_name, *arguments)
  • call: proc_or_lambda.call(*arguments)

Which methods will an object respond to?

To see which methods an object responds to, simply use the object’s methods method.

To see if a Class responds to a given method, use the respond_to? method.

Deleting Methods

You also have the ability to delete methods using the undef_method statement.

Aliasing Methods

Finally, you can alias methods using the alias statement. There are a few good reasons for aliases.

Backward Compatibility: When you rename a method, existing code that relies on the old method name might break. Aliasing allows you to provide the new method name while still supporting the old one.

Enhancing or Modifying Behavior: You might want to add additional behavior to an existing method without altering its original implementation. Aliasing the method allows you to extend its functionality while preserving the original behavior.

Improving Method Names: Sometimes, the original method name might not be intuitive. Aliasing allows you to provide a more descriptive or meaningful name without changing the original method name.

Static Methods

Occasionally you will have methods that don’t access any class variables, which can then be defined as static methods. This is accomplished in Ruby by prefixing the method name with self.

Although the static method cannot access any instance variables because it doesn’t have a corresponding object, it can access constants and class variables.

Exiting a Method

Like almost any other programming language, Ruby executes statements in the sequence of their appearance in your code. Also, as with any other language, there are statements that can be used for flow control and forcing a method exit. A Ruby method will execute until its last statement and can, but doesn’t need to, explicitly end the method with the return statement. The return statement can be used by itself or with values. If the return statement is issued without any value, the method will return the value of nil.

You can interrupt program execution anywhere and force method termination by placing the return statement at the appropriate point.

You can also establish a block of code that will always be executed when the method completes, by using the ensure statement.