Interpolación de cadenas en Ruby: #{} y format
Interpolar es rellenar los huecos de una plantilla: escribes el texto fijo y marcas con #{} dónde va cada valor; Ruby rellena el hueco al ejecutar el programa.
La sintaxis: #{}
nombre = "Ana"
puts "Hola #{nombre}" # Hola Ana
Dentro de las llaves puedes poner cualquier expresión, no solo una variable:
puts "2 + 3 = #{2 + 3}" # 2 + 3 = 5
puts "En mayúsculas: #{nombre.upcase}" # En mayúsculas: ANA
Comillas dobles frente a comillas simples
Solo las comillas dobles interpolan. Con comillas simples, Ruby entiende que todo es texto literal:
nombre = "Ana"
puts "Hola #{nombre}" # Hola Ana
puts 'Hola #{nombre}' # Hola #{nombre}
Usa comillas simples cuando quieras justo eso: que el texto salga tal cual, sin sustituciones.
Escribir #{ sin que se interpole
Si necesitas que aparezca #{ tal cual dentro de comillas dobles, escápalo con una barra invertida:
puts "Usa \#{nombre} para interpolar" # Usa #{nombre} para interpolar
puts 'Usa #{nombre} para interpolar' # Usa #{nombre} para interpolar
Y un atajo que verás en código ajeno: con variables de instancia o globales, las llaves son opcionales. "Hola #@nombre" funciona igual que "Hola #{@nombre}". Con llaves se lee mejor y funciona con cualquier expresión, así que es la forma que se usa en este artículo.
@nombre = "Ana"
puts "Hola #@nombre" # Hola Ana
Por qué interpolar en vez de concatenar con +
Con + solo puedes unir textos. Si uno de los valores es un número, Ruby se queja:
edad = 30
puts "Tengo " + edad + " años"
# TypeError: no implicit conversion of Integer into String
puts "Tengo " + edad.to_s + " años" # funciona, pero es más largo
puts "Tengo #{edad} años" # Tengo 30 años
La interpolación llama a to_s por ti, así que funciona con números, arrays o tus propios objetos (si definen to_s, como ves en Clases en Ruby). Con nil deja el hueco vacío:
nada = nil
puts "Valor: [#{nada}]" # Valor: []
puts, print y printf
| Método | Qué hace |
|---|---|
puts (put string) |
Escribe el texto y añade un salto de línea al final |
print |
Escribe el texto sin salto de línea |
printf |
Escribe con un formato (%s, %d, %.2f…) y sin salto de línea |
texto1 = "Hola"
texto2 = "Mundo"
puts "#{texto1} #{texto2}"
print "#{texto1} #{texto2}\n"
printf("%s %s\n", texto1, texto2)
# Hola Mundo
# Hola Mundo
# Hola Mundo
Formatear números: format
Cuando necesitas decimales fijos o ceros a la izquierda, format (o el operador %) devuelve el texto ya formateado:
puts format("%.2f €", 3.14159) # 3.14 €
puts format("%05d", 42) # 00042
puts "Precio: %.2f €" % 9.5 # Precio: 9.50 €
Con nombres y en columnas
Con varios valores, es fácil confundir el orden. format acepta nombres, con %<nombre>, y así cada hueco dice qué va en él:
puts format("%<producto>s: %<precio>.2f €", producto: "Pan", precio: 1.5) # Pan: 1.50 €
Un número delante de la letra fija el ancho, y un -, que se alinee a la izquierda. Sirve para sacar tablas sencillas en la terminal:
[["Pan", 1.5], ["Leche", 0.99], ["Aceite", 12]].each do |producto, precio|
puts format("%-8s%6.2f €", producto, precio)
end
Pan 1.50 €
Leche 0.99 €
Aceite 12.00 €
Textos de varias líneas: heredoc
Para textos largos, un heredoc (<<~) también interpola y quita la sangría común:
nombre = "Ana"
edad = 30
mensaje = <<~TEXTO
Hola #{nombre},
tienes #{edad} años.
TEXTO
puts mensaje
# Hola Ana,
# tienes 30 años.
Si quieres un heredoc que no interpole, pon el nombre entre comillas simples, igual que con un texto corto:
nombre = "Ana"
plantilla = <<~'TEXTO'
Hola #{nombre}
TEXTO
puts plantilla # Hola #{nombre}
Errores frecuentes
1. Olvidar las llaves o la almohadilla. Hacen falta las dos cosas, # y {}. Con solo una, el texto sale tal cual y no hay error:
nombre = "Ana"
puts "Hola #nombre" # Hola #nombre
puts "Hola {nombre}" # Hola {nombre}
puts "Hola #{nombre}" # Hola Ana
2. Un hueco vacío que nadie ve. Como nil se convierte en texto vacío, un dato que falta no da error: deja un hueco. Pasa mucho con hashes cuyas claves son textos y no símbolos:
usuario = { "nombre" => "Ana" }
puts "Hola #{usuario[:nombre]}, bienvenida" # Hola , bienvenida
Si el dato tiene que estar, pídelo con fetch, que falla en el sitio y te dice qué falta:
puts "Hola #{usuario.fetch(:nombre)}" # el mismo usuario de arriba, con la clave "nombre"
key not found: :nombre (KeyError)
La diferencia entre "nombre" y :nombre se explica en Símbolos en Ruby.
3. Interpolar un objeto que no define to_s. Sale el nombre de la clase y una dirección de memoria:
class Coche
def initialize(color) = @color = color
end
puts "Tu coche: #{Coche.new("rojo")}"
Tu coche: #<Coche:0x00007f006d443080>
Define to_s en la clase, como se explica en Clases en Ruby.
4. Dar a format menos valores que huecos. Al contrario que la interpolación, format sí avisa:
puts format("%s tiene %d años", "Ana")
too few arguments (ArgumentError)
5. Pasar un texto que no es un número a un hueco de número. %d convierte el valor con Integer(): "3" vale y 3.7 se queda en 3, pero "tres" no es un número:
puts format("%d unidades", "tres")
invalid value for Integer(): "tres" (ArgumentError)
Compruébalo con un test
El formato de un texto también es comportamiento, y un test lo fija. Este método prepara la etiqueta de precio de un producto. La primera versión, con interpolación directa, parece correcta:
require "minitest/autorun"
def etiqueta(producto, precio)
"#{producto}: #{precio} €"
end
class EtiquetaTest < Minitest::Test
def test_siempre_muestra_dos_decimales
assert_equal "Pan: 1.50 €", etiqueta("Pan", 1.5)
end
end
ruby etiqueta_test.rb
EtiquetaTest#test_siempre_muestra_dos_decimales [etiqueta_test.rb:9]:
Expected: "Pan: 1.50 €"
Actual: "Pan: 1.5 €"
1.5 se convierte en "1.5", sin el cero. Con format, el test pasa, y uno más comprueba que se redondea al céntimo:
require "minitest/autorun"
def etiqueta(producto, precio)
format("%<producto>s: %<precio>.2f €", producto: producto, precio: precio)
end
class EtiquetaTest < Minitest::Test
def test_siempre_muestra_dos_decimales
assert_equal "Pan: 1.50 €", etiqueta("Pan", 1.5)
assert_equal "Leche: 1.00 €", etiqueta("Leche", 1)
end
def test_redondea_al_centimo
assert_equal "Queso: 3.33 €", etiqueta("Queso", 10 / 3.0)
end
end
2 runs, 3 assertions, 0 failures, 0 errors, 0 skips
Para empezar con tests en Ruby, lee la introducción al testing en Ruby.
Cuándo no interpolar
Interpolar es perfecto para mensajes, etiquetas y textos que lee una persona. Pero cuando el texto lo va a interpretar otro programa, meter datos de fuera puede cambiar lo que ese programa hace:
- HTML. Si el dato viene de un usuario, puede traer etiquetas. Escápalo antes de meterlo:
require "erb"
comentario = "<script>alert('hola')</script>"
puts "<p>#{comentario}</p>"
puts "<p>#{ERB::Util.html_escape(comentario)}</p>"
<p><script>alert('hola')</script></p>
<p><script>alert('hola')</script></p>
En la primera línea, el navegador ejecutaría el <script>; en la segunda, solo lo muestra. Las plantillas de Rails escapan por ti lo que pones con <%= %>, como se ve en la diferencia entre <% %> y <%= %>.
- Comandos del sistema.
system("echo #{nombre}")pasa el texto a la shell, y un;ennombrecuela otro comando. Pasa cada argumento por separado: lo tienes en ejecución de comandos del sistema desde Ruby. - Consultas SQL. Por el mismo motivo, nunca metas datos del usuario en una consulta con
#{}: es la puerta de la inyección SQL. Usa los parámetros de la librería de base de datos, que separan la consulta de los datos.
Ejercicio de cinco minutos
- Copia el primer test de
etiqueta, comprueba que falla y arréglalo conformat. - Añade un test para un precio de 1234.5. ¿Qué devuelve
format("%.2f", 1234.5)? ¿Pone separador de miles? - Escribe un heredoc con tu nombre y tu edad interpolados. Después pon el nombre del heredoc entre comillas simples y mira qué cambia.
Fuentes
Comprobado en noviembre de 2026 en la documentación oficial de Ruby 4.0: literales de cadena e interpolación (escapar la # desactiva la interpolación; #@foo como atajo de #{@foo}; un heredoc con el identificador entre comillas simples no interpola), Kernel (puts, print, printf, format) y especificaciones de formato (referencias por nombre con %<nombre>, ancho y alineación).
Los ejemplos del artículo original se ejecutaron el 7 de noviembre de 2026 con Ruby 4.0.9 (imagen oficial ruby:latest de Docker). Los nuevos (escapar #{, #@nombre, format con nombres y columnas, el heredoc sin interpolación, los errores frecuentes, el test y el escapado de HTML con ERB::Util.html_escape) se han ejecutado el 11 de noviembre de 2026 en Docker con las imágenes ruby:3.4 (Ruby 3.4.12, Minitest 5.25.4) y ruby:4.0 (Ruby 4.0.9, Minitest 6.0.0), con la misma salida en las dos. Las salidas de error están recortadas a las líneas que importan; la dirección del objeto cambia en cada ejecución.