Vitamin C

Ruby Language Methods


Functions in Ruby provide organized, reusable code to preform a set of actions. Functions simplify the coding process, prevent redundant logic, and make code easier to follow. This topic describes the declaration and utilization of functions, arguments, parameters, yield statements and scope in Ruby.


A method is a named block of code, associated with one or more objects and generally identified by a list of parameters in addition to the name.

def hello(name)
  "Hello, #{name}"

A method invocation specifies the method name, the object on which it is to be invoked (sometimes called the receiver), and zero or more argument values that are assigned to the named method parameters. The value of the last expression evaluated in the method becomes the value of the method invocation expression.

# => "Hello, World"

When the receiver is not explicit, it is self.

# => main

# => "Hello, World"

As explained in the Ruby Programming Language book, many languages distinguish between functions, which have no associated object, and methods, which are invoked on a receiver object. Because Ruby is a purely object-oriented language, all methods are true methods and are associated with at least one object.

Overview of Method Parameters

TypeMethod SignatureCall ExampleAssignments
Requireddef fn(a,b,c)fn(2,3,5)a=2, b=3, c=5
Variadicdef fn(*rest)fn(2,3,5)rest=[2, 3, 5]
Defaultdef fn(a=0,b=1)fn(2,3)a=2, b=3
Keyworddef fn(a:0,b:1)fn(a:2,b:3)a=2, b=3

These argument types can be combined in virtually any way you can imagine to create variadic functions. The minimum number of arguments to the function will equal the amount of required arguments in the signature. Extra arguments will be assigned to default parameters first, then to the *rest parameter.

TypeMethod SignatureCall ExampleAssignments
R,D,V,Rdef fn(a,b=1,*mid,z)fn(2,97)a=2, b=1, mid=[], z=97
fn(2,3,97)a=2, b=3, mid=[], z=97
fn(2,3,5,97)a=2, b=3, mid=[5], z=97
fn(2,3,5,7,97)a=2, b=3, mid=[5,7], z=97
R,K,Kdef fn(a,g:6,h:7)fn(2)a=2, g=6, h=7
fn(2,h:19)a=2, g=6, h=19
fn(2,g:17,h:19)a=2, g=17, h=19
VKdef fn(**ks)fn(a:2,g:17,h:19)ks={a:2, g:17, h:19}
fn(four:4,five:5)ks={four:4, five:5}

Single required parameter

def say_hello_to(name)
    puts "Hello #{name}"

say_hello_to('Charles')    # Hello Charles

Multiple required parameters

def greet(greeting, name)
    puts "#{greeting} #{name}"

greet('Hi', 'Sophie')    # Hi Sophie

Default parameters

def make_animal_sound(sound = 'Cuack')
    puts sound

make_animal_sound('Mooo') # Mooo
make_animal_sound         # Cuack

It's possible to include defaults for multiple arguments:

def make_animal_sound(sound = 'Cuack', volume = 11)
    play_sound(sound, volume)

make_animal_sound('Mooo') # Spinal Tap cow

However, it's not possible to supply the second without also supplying the first. Instead of using positional parameters, try keyword parameters:

def make_animal_sound(sound: 'Cuack', volume: 11)
    play_sound(sound, volume)

make_animal_sound(volume: 1) # Duck whisper

Or a hash parameter that stores options:

def make_animal_sound(options = {})
    options[:sound]  ||= 'Cuak'
    options[:volume] ||= 11
    play_sound(sound, volume)

make_animal_sound(:sound => 'Mooo') 

Default parameter values can be set by any ruby expression. The expression will run in the context of the method, so you can even declare local variables here. Note, won't get through code review. Courtesy of caius for pointing this out.

def make_animal_sound( sound = ( raise 'TUU-too-TUU-too...' ) ); p sound; end

make_animal_sound 'blaaaa' # => 'blaaaa'
make_animal_sound          # => TUU-too-TUU-too... (RuntimeError)

Optional parameter(s) (splat operator)

def welcome_guests(*guests)
    guests.each { |guest| puts "Welcome #{guest}!" }

welcome_guests('Tom')    # Welcome Tom!
welcome_guests('Rob', 'Sally', 'Lucas') # Welcome Rob!
                                        # Welcome Sally!
                                        # Welcome Lucas!

Note that welcome_guests(['Rob', 'Sally', 'Lucas']) will output Welcome ["Rob", "Sally", "Lucas"]!
Instead, if you have a list, you can do welcome_guests(*['Rob', 'Sally', 'Lucas']) and that will work as welcome_guests('Rob', 'Sally', 'Lucas').

Required default optional parameter mix

def my_mix(name,valid=true, *opt)
    puts name
    puts valid
    puts opt

Call as follows:

# 'me'
# true
# []

my_mix('me', false)
# 'me'
# false
# []

my_mix('me', true, 5, 7) 
# 'me'
# true
# [5,7]

Method Definitions are Expressions

Defining a method in Ruby 2.x returns a symbol representing the name:

class Example
  puts def hello

#=> :hello

This allows for interesting metaprogramming techniques. For instance, methods can be wrapped by other methods:

class Class
  def logged(name)
    original_method = instance_method(name)
    define_method(name) do |*args|
      puts "Calling #{name} with #{args.inspect}."
      puts "Completed #{name}."

class Meal
  def initialize
    @food = []
  logged def add(item)
    @food << item

meal =
meal.add "Coffee"
# Calling add with ["Coffee"].
# Completed add.

Capturing undeclared keyword arguments (double splat)

The ** operator works similarly to the * operator but it applies to keyword parameters.

def options(required_key:, optional_key: nil, **other_options)

options(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> { :foo => "Foo!", :bar => "Bar!" }

In the above example, if the **other_options is not used, an ArgumentError: unknown keyword: foo, bar error would be raised.

def without_double_splat(required_key:, optional_key: nil)
  # do nothing

without_double_splat(required_key: 'Done!', foo: 'Foo!', bar: 'Bar!')
#> ArgumentError: unknown keywords: foo, bar

This is handy when you have a hash of options that you want to pass to a method and you do not want to filter the keys.

def options(required_key:, optional_key: nil, **other_options)

my_hash = { required_key: true, foo: 'Foo!', bar: 'Bar!' }

#> { :foo => "Foo!", :bar => "Bar!" }

It is also possible to unpack a hash using the ** operator. This allows you to supply keyword directly to a method in addition to values from other hashes:

my_hash = { foo: 'Foo!', bar: 'Bar!' }

options(required_key: true, **my_hash)
#> { :foo => "Foo!", :bar => "Bar!" }

Yielding to blocks

You can send a block to your method and it can call that block multiple times. This can be done by sending a proc/lambda or such, but is easier and faster with yield:

def simple(arg1,arg2)
  puts "First we are here:  #{arg1}"
  puts "Finally we are here:  #{arg2}"
simple('start','end') { puts "Now we are inside the yield" }

#> First we are here:  start
#> Now we are inside the yield
#> Finally we are here:  end
#> Now we are inside the yield

Note that the { puts ... } is not inside the parentheses, it implicitly comes after. This also means we can only have one yield block. We can pass arguments to the yield:

def simple(arg)
  puts "Before yield"
  puts "After yield"
simple('Dave') { |name| puts "My name is #{name}" }

#> Before yield
#> My name is Dave
#> After yield

With yield we can easily make iterators or any functions that work on other code:

def countdown(num)
  num.times do |i|

countdown(5) { |i| puts "Call number #{i}" }

#> Call number 5
#> Call number 4
#> Call number 3
#> Call number 2
#> Call number 1

In fact, it is with yield that things like foreach, each and times are generally implemented in classes.

If you want to find out if you have been given a block or not, use block_given?:

class Employees
  def names
    ret = []
    @employees.each do |emp|
      if block_given?


This example assumes that the Employees class has an @employees list that can be iterated with each to get objects that have employee names using the name method. If we are given a block, then we'll yield the name to the block, otherwise we just push it to an array that we return.

Tuple Arguments

A method can take an array parameter and destructure it immediately into named local variables. Found on Mathias Meyer's blog.

def feed( amount, (animal, food) )

    p "#{amount} #{animal}s chew some #{food}"


feed 3, [ 'rabbit', 'grass' ] # => "3 rabbits chew some grass"

Defining a method

Methods are defined with the def keyword, followed by the method name and an optional list of parameter names in parentheses. The Ruby code between def and end represents the body of the method.

def hello(name)
  "Hello, #{name}"

A method invocation specifies the method name, the object on which it is to be invoked (sometimes called the receiver), and zero or more argument values that are assigned to the named method parameters.

# => "Hello, World"

When the receiver is not explicit, it is self.

Parameter names can be used as variables within the method body, and the values of these named parameters come from the arguments to a method invocation.

# => "Hello, World"
# => "Hello, All"

Use a function as a block

Many functions in Ruby accept a block as an argument. E.g.:

[0, 1, 2].map {|i| i + 1}
 => [1, 2, 3]

If you already have a function that does what you want, you can turn it into a block using &method(:fn):

def inc(num)
   num + 1

[0, 1, 2].map &method(:inc)
 => [1, 2, 3]

Got any Ruby Language Question?