Control del flujo en Ruby para tomar decisiones y repetir acciones

Capítulo 3

Tiempo estimado de lectura: 7 minutos

+ Ejercicio

Condicionales: tomar decisiones con claridad

El control de flujo permite que tu programa elija caminos (decisiones) y repita acciones (iteración). En Ruby, las estructuras son expresivas y suelen leerse casi como lenguaje natural.

if / elsif / else

Úsalos cuando necesites evaluar condiciones en orden. La primera condición verdadera ejecuta su bloque.

edad = 20
if edad >= 18
  puts "Mayor de edad"
elsif edad >= 13
  puts "Adolescente"
else
  puts "Niñez"
end

En Ruby, if también puede usarse en una sola línea cuando es simple:

puts "Acceso" if permitido

unless

unless es el inverso de if: ejecuta el bloque si la condición es falsa. Es útil para evitar dobles negaciones.

puts "Debes iniciar sesión" unless autenticado

Evita combinar unless con else en lógica compleja; suele ser más legible un if.

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

case (cuando hay múltiples opciones)

case es ideal para seleccionar entre varias alternativas según un valor.

opcion = 2
case opcion
when 1
  puts "Crear"
when 2
  puts "Listar"
when 3
  puts "Salir"
else
  puts "Opción inválida"
end

También puedes usar rangos o múltiples valores:

nota = 8
case nota
when 0..4 then puts "Insuficiente"
when 5..6 then puts "Suficiente"
when 7..8 then puts "Notable"
when 9..10 then puts "Excelente"
end

Operadores lógicos y comparaciones

Las condiciones se construyen con comparaciones y operadores lógicos.

  • Comparación: ==, !=, >, >=, <, <=
  • Lógicos: && (y), || (o), ! (no)
edad = 20
pais = "AR"
permitido = (edad >= 18) && (pais == "AR" || pais == "UY")
puts permitido

Consejo: usa paréntesis para dejar clara la intención cuando combinas && y ||.

Valores “truthy” y “falsy”

En Ruby, solo false y nil son falsos. Todo lo demás (incluido 0 y cadenas vacías) se considera verdadero.

puts "verdadero" if 0
puts "verdadero" if ""

Bucles: repetir acciones

while y until

while repite mientras la condición sea verdadera. until repite hasta que la condición sea verdadera (es decir, mientras sea falsa).

i = 1
while i <= 3
  puts i
  i += 1
end
i = 1
until i > 3
  puts i
  i += 1
end

times (repetición por cantidad)

Cuando sabes cuántas veces repetir, times es idiomático.

3.times do |n|
  puts "Vuelta #{n}"
end

each (recorrer elementos)

each recorre una colección y ejecuta un bloque por elemento.

nombres = ["Ana", "Luis", "Marta"]
nombres.each do |nombre|
  puts "Hola, #{nombre}"
end

loop (bucle infinito controlado)

loop se usa cuando quieres repetir indefinidamente y salir con break según una condición interna.

contador = 0
loop do
  contador += 1
  break if contador == 3
end

Control de iteración: break y next

Estas palabras clave te permiten controlar el flujo dentro de un bucle.

  • break: termina el bucle.
  • next: salta a la siguiente iteración.
(1..10).each do |n|
  next if n.even?      # salta pares
  break if n > 7       # corta al pasar 7
  puts n               # imprime 1,3,5,7
end

Patrones típicos

1) Validación de entrada (repetir hasta que sea válida)

En consola, es común pedir un dato y validar hasta que cumpla reglas. El patrón suele ser: pedir → validar → repetir si falla.

Ejemplo: pedir un número entero positivo

numero = nil
loop do
  print "Ingresa un entero positivo: "
  entrada = gets
  break if entrada.nil?  # por si se cierra la entrada

  entrada = entrada.strip
  if entrada.match?(/\A\d+\z/) && entrada.to_i > 0
    numero = entrada.to_i
    break
  else
    puts "Entrada inválida. Intenta de nuevo."
  end
end
puts "Elegiste: #{numero}"

2) Menús de consola (case + loop)

Un menú típico se repite hasta que el usuario elige salir. Se combina loop con case y break.

loop do
  puts "\n--- MENÚ ---"
  puts "1) Saludar"
  puts "2) Mostrar hora"
  puts "3) Salir"
  print "Elige una opción: "

  opcion = gets
  break if opcion.nil?

  case opcion.strip
  when "1"
    print "Nombre: "
    nombre = gets&.strip
    puts "Hola, #{nombre}"
  when "2"
    puts "Hora: #{Time.now}"
  when "3"
    puts "Saliendo..."
    break
  else
    puts "Opción inválida"
  end
end

3) Recorridos con acumuladores

Un acumulador es una variable que “junta” resultados mientras recorres elementos (sumas, conteos, concatenaciones, máximos, etc.).

Ejemplo: sumar solo valores válidos

valores = [10, -2, 7, 0, 3]
suma = 0
valores.each do |v|
  next if v <= 0
  suma += v
end
puts suma  # 20

Ejercicios aplicados (con guía paso a paso)

Ejercicio 1: Validador de contraseña simple

Objetivo: pedir una contraseña hasta que cumpla reglas mínimas: longitud ≥ 8, al menos una mayúscula y al menos un número.

Paso a paso:

  • 1) Repetir con loop hasta que sea válida.
  • 2) Leer entrada con gets y limpiar con strip.
  • 3) Evaluar reglas con expresiones regulares y comparaciones.
  • 4) Si falla, mostrar qué regla no se cumple y continuar.
  • 5) Si pasa, salir con break.
def valida_password?(pwd)
  return false if pwd.nil?
  return false if pwd.length < 8
  return false unless pwd.match?(/[A-Z]/)
  return false unless pwd.match?(/\d/)
  true
end

loop do
  print "Crea una contraseña (8+, 1 mayúscula, 1 número): "
  pwd = gets&.strip
  break if pwd.nil?

  if valida_password?(pwd)
    puts "Contraseña aceptada"
    break
  else
    puts "No cumple requisitos."
    puts "- Mínimo 8 caracteres" if pwd.length < 8
    puts "- Debe incluir una mayúscula" unless pwd.match?(/[A-Z]/)
    puts "- Debe incluir un número" unless pwd.match?(/\d/)
  end
end

Ejercicio 2: Menú interactivo (mini gestor)

Objetivo: crear un menú que permita agregar elementos a una lista, verlos y salir.

Paso a paso:

  • 1) Crear una lista vacía.
  • 2) Iniciar un loop para mostrar el menú.
  • 3) Leer opción y usar case.
  • 4) En “Agregar”, pedir texto y guardarlo.
  • 5) En “Listar”, recorrer con each y mostrar índice.
  • 6) En “Salir”, usar break.
items = []

loop do
  puts "\n--- LISTA ---"
  puts "1) Agregar"
  puts "2) Listar"
  puts "3) Borrar último"
  puts "4) Salir"
  print "Opción: "

  opcion = gets
  break if opcion.nil?

  case opcion.strip
  when "1"
    print "Nuevo ítem: "
    texto = gets&.strip
    if texto.nil? || texto.empty?
      puts "No se agregó (vacío)."
      next
    end
    items << texto
    puts "Agregado."
  when "2"
    if items.empty?
      puts "Lista vacía."
    else
      items.each_with_index do |item, idx|
        puts "#{idx + 1}. #{item}"
      end
    end
  when "3"
    if items.empty?
      puts "Nada para borrar."
    else
      borrado = items.pop
      puts "Borrado: #{borrado}"
    end
  when "4"
    break
  else
    puts "Opción inválida"
  end
end

Ejercicio 3: Contador con reglas (múltiplos y sustituciones)

Objetivo: imprimir del 1 al N, pero con reglas: si es múltiplo de 3 imprimir "Fizz", si es múltiplo de 5 imprimir "Buzz", si es múltiplo de ambos imprimir "FizzBuzz". Además, contar cuántas sustituciones se hicieron.

Paso a paso:

  • 1) Pedir N y validarlo como entero positivo.
  • 2) Recorrer con 1.upto(n) o each sobre un rango.
  • 3) Usar condicionales para decidir qué imprimir.
  • 4) Mantener acumuladores para contar Fizz, Buzz y FizzBuzz.
n = nil
loop do
  print "N (entero positivo): "
  entrada = gets
  break if entrada.nil?

  entrada = entrada.strip
  if entrada.match?(/\A\d+\z/) && entrada.to_i > 0
    n = entrada.to_i
    break
  else
    puts "Entrada inválida."
  end
end

fizz = 0
buzz = 0
fizzbuzz = 0

(1..n).each do |i|
  if (i % 3 == 0) && (i % 5 == 0)
    puts "FizzBuzz"
    fizzbuzz += 1
  elsif i % 3 == 0
    puts "Fizz"
    fizz += 1
  elsif i % 5 == 0
    puts "Buzz"
    buzz += 1
  else
    puts i
  end
end

puts "--- Resumen ---"
puts "Fizz: #{fizz}"
puts "Buzz: #{buzz}"
puts "FizzBuzz: #{fizzbuzz}"

Tabla rápida: ¿cuándo usar cada estructura?

Necesitas...Usa...Ejemplo típico
Elegir entre pocas condicionesif/elsif/elseValidar rangos o reglas
Ejecutar si NO se cumple algounless“Mostrar error a menos que…”
Muchas opciones por valorcaseMenús, estados, comandos
Repetir mientras condiciónwhileLeer hasta cumplir
Repetir hasta condiciónuntilEsperar hasta que ocurra
Repetir N vecestimesIntentos, simulaciones
Recorrer coleccióneachProcesar elementos
Bucle controlado internamenteloop + breakMenús interactivos

Ahora responde el ejercicio sobre el contenido:

En Ruby, ¿qué estructura es más adecuada cuando quieres repetir indefinidamente y salir según una condición interna usando break (por ejemplo, en un menú interactivo)?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

loop se usa para repetir sin un fin predeterminado y se corta cuando una condición interna ejecuta break, un patrón típico en menús de consola.

Siguiente capítulo

Métodos en Ruby y bloques para reutilizar lógica

Arrow Right Icon
Portada de libro electrónico gratuitaRuby desde Cero para principiantes: Programación Moderna, Clara y Eficiente
30%

Ruby desde Cero para principiantes: Programación Moderna, Clara y Eficiente

Nuevo curso

10 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.