Métodos
Eventualmente vas tener algunas líneas de código que necesitan ser ejecutadas varias veces y desde diferentes partes de tu programa. En vez de repetir el mismo código una y otra vez puedes crear un método (también se les conoce como procedimientos o funciones en otros lenguajes de programación) e invocarlo cada vez que necesites ejecutar ese trozo de código.
Crea un archivo llamado methods.rb y escribe lo siguiente:
def hello
puts "Hola mundo"
end
Para definir un método usamos la palabra reservada def y le damos un nombre (en este caso hello). Al final debemos cerrar el método con end.
$ ruby methods.rb
Si lo ejecutas no debería salir nada. Una característica de los métodos es que no son ejecutados hasta que no los invoquemos. Modifiquemos nuestro programa para invocarlo:
def hello
puts "Hola mundo"
end
hello() # acá lo invocamos, los paréntesis son opcionales
En la última línea lo estamos invocando. Si lo ejecutas ahora si debería aparecer "Hola mundo":
$ ruby methods.rb
Hola mundo

Parámetros

Los métodos pueden recibir cero o más parámetros (o argumentos). Modifiquemos nuestro programa para que salude a cualquier persona:
def hello(name)
puts "Hola #{name}"
end
hello("Germán")
hello("David")
Si lo ejecutamos deberías ver lo siguiente:
$ ruby methods.rb
Hola Germán
Hola David

Retornando un valor

En Ruby todas las expresiones retornan un valor. Incluso puts "Hola mundo" retorna un valor, solo que el valor es nil (una forma de decir "nada").
Por defecto, todos los métodos retornan el resultado de la última línea que se ejecute en el método. Vamos a modificar nuestro ejemplo para que en vez de imprimir el saludo, lo retorne:
def hello(name)
"Hola #{name}"
end
puts hello("Germán")
puts hello "David" # los paréntesis son opcionales
Fíjate que ya no hacemos el puts dentro de la función, así que nos toca hacerlo al invocar el método. Pero es mejor práctica así. El problema es que cuando el puts está dentro de la función, esa función solo nos serviría en aplicaciones de consola. Si la queremos usar en una aplicación Web no serviría (el puts es únicamente para imprimir en la consola).
$ ruby methods.rb
Hola Germán
Hola David
También es posible retornar el valor explícitamente con la palabra reservada return:
def hello(name)
return "Hola #{name}"
end
puts hello("Germán")
puts hello "David"
El resultado cuando lo ejecutes debe seguir siendo el mismo.
En general, los programadores de Ruby tienden a omitir el return a menos de que sea completamente necesario.

Un ejemplo

Hagamos un programa que nos diga de qué generación somos dependiendo de nuestro año de nacimiento. Las generaciones son las siguientes:
Nacidos <= 1945 - la gran generación
Nacidos entre 1946 y 1964 - baby boomers
Nacidos entre 1965 y 1982 - generación x
Nacidos entre 1983 y 2004 - milenials
Nacidos >= 2005 - centenials
Vamos ahora a hacer un método que nos diga la generación y lo invocamos con lo que ingrese el usuario. Crea un archivo llamado generation_method.rb y escribe lo siguiente:
def generation(year_of_birth)
if year_of_birth >= 1996
puts "Eres un centenial"
elsif year_of_birth >= 1977
puts "Eres un millenial"
elsif year_of_birth >= 1965
puts "Eres generación X"
elsif year_of_birth >= 1946
puts "Eres baby boomer"
else
puts "Eres tradicionalista"
end
end
print "¿Cuál es tu año de nacimiento? "
year_of_birth = gets.chomp.to_i
generation(year_of_birth)
Si la ejecutas debería decirte la generación dependiendo de tu año de nacimiento:
$ ruby generation_method.rb
¿Cuál es tu año de nacimiento? 1982
Eres un millenial
Sin embargo, sería mucho mejor evitar el puts en el método. Modifiquémoslo para mejorarlo:
def generation(year_of_birth)
if year_of_birth >= 1996
"Eres un centenial"
elsif year_of_birth >= 1977
"Eres un millenial"
elsif year_of_birth >= 1965
"Eres generación X"
elsif year_of_birth >= 1946
"Eres baby boomer"
else
"Eres tradicionalista"
end
end
print "¿Cuál es tu año de nacimiento? "
year_of_birth = gets.chomp.to_i
puts generation(year_of_birth)
Mucho mejor. Sin embargo hay algo que no me gusta de este método. Está retornando los strings en Español. Si quisiéramos comparar ese valor para realizar alguna acción dependiendo de la generación, nos tocaría comparar el string exacto. Además, si queremos tener una aplicación que soporte varios idiomas esta implementación no va a funcionar. Podemos mejorarla:
def generation(year_of_birth)
if year_of_birth >= 1996
:centenial
elsif year_of_birth >= 1977
:millenial
elsif year_of_birth >= 1965
:generation_x
elsif year_of_birth >= 1946
:baby_boomer
else
:traditionalist
end
end
translations = { centenial: "centenial", millenial: "millenial", generation_x: "X",
baby_boomer: "baby boomer", traditionalist: "tradicionalista" }
print "¿Cuál es tu año de nacimiento? "
year_of_birth = gets.chomp.to_i
generation_code = generation(year_of_birth)
puts "Eres de la generación #{translations[generation_code]}"
El programa es más largo pero la función generation es ahora mucho más reutilizable. Si queremos tomar una desición dependiendo de la generación lo podemos hacer fácilmente (comparar símbolos es mucho menos propenso a errores que comparar cadenas de texto).

Evalúate

  1. 1.
    Escribe un método llamado square_perimeter que reciba un argumento side y calcule el perímetro de un cuadrado (recuerda que el perímetro de un cuadrado es la suma de los lados). Por ejemplo:
    square_perimeter(2) # Debería retornar 8
    square_perimeter(5) # Debería retornar 20
  2. 2.
    Escribe un método llamado square_area que reciba un argumento side y retorne el área de de un cuadrado. Por ejemplo:
    square_area(2) # Debería retornar 4
    square_area(5) # Debería retornar 25
  3. 3.
    Escribe un método llamado sum que reciba un arreglo y retorne la suma de los elementos. Por ejemplo:
    sum([]) # debería retornar 0
    sum([1]) # debería retornar 1
    sum([1, 2, 3]) # debería retornar 6
  4. 4.
    Escribe un método llamado average que reciba un arreglo y retorne el promedio de los elementos. Por ejemplo:
    average([]) # debería retornar 0
    average([1]) # debería retornar 1
    average([1, 2, 3]) # debería retornar 2