summaryrefslogtreecommitdiffhomepage
path: root/es-es/ruby-es.html.markdown
blob: 8b703df13588628c7ad4791c7a4aa27668e5132a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
---
language: ruby
filename: learnruby-es.rb
contributors:
  - ["David Underwood", "http://theflyingdeveloper.com"]
  - ["Joel Walden", "http://joelwalden.net"]
  - ["Luke Holder", "http://twitter.com/lukeholder"]
  - ["Tristan Hume", "http://thume.ca/"]
  - ["Nick LaMuro", "https://github.com/NickLaMuro"]
  - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"]
  - ["Ariel Krakowski", "http://www.learneroo.com"]
  - ["Dzianis Dashkevich", "https://github.com/dskecse"]
  - ["Levi Bostian", "https://github.com/levibostian"]
  - ["Rahil Momin", "https://github.com/iamrahil"]
  - ["Gabriel Halley", "https://github.com/ghalley"]
  - ["Persa Zula", "http://persazula.com"]
translators:
    - ["Camilo Garrido", "http://www.twitter.com/hirohope"]
    - ["Erick Bernal", "http://www.twitter.com/billowkib"]
lang: es-es
---

```ruby
# Esto es un comentario

=begin
Este es un comentario multilínea
Nadie los usa.
Tu tampoco deberías
=end

# En primer lugar: Todo es un objeto

# Los números son objetos

3.class #=> Fixnum

3.to_s #=> "3"


# Un poco de aritmética básica
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
2**5 #=> 32
5 % 3 #=> 2

# La aritmética es sólo azúcar sintáctico
# para llamar un método de un objeto
1.+(3) #=> 4
10.* 5 #=> 50

# Los valores especiales son objetos
nil # Nada que ver aqui
true # Verdadero
false # Falso

nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass

# Igualdad
1 == 1 #=> true
2 == 1 #=> false

# Desigualdad
1 != 1 #=> false
2 != 1 #=> true

# Además de 'false', 'nil' es otro valor falso

!nil   #=> true
!false #=> true
!0     #=> false

# Más comparaciones
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true

# Operadores lógicos
true && false #=> false
true || false #=> true
!true #=> false

# Existen versiones alternativas de los operadores lógicos con menor prioridad
# Estos son usados como constructores controladores de flujo que encadenan
# sentencias hasta que una de ellas retorne verdadero o falso

# `haz_otra_cosa` solo se llama si `haz_algo` retorna verdadero.
haz_algo() and haz_otra_cosa()
# `registra_error` solo se llama si `haz_algo` falla
haz_algo() or registra_error()


# Los strings son objetos

'Soy un string'.class #=> String
"Soy un string también".class #=> String

referente = "usar interpolación de strings"
"Yo puedo #{referente} usando strings de comillas dobles"
#=> "Yo puedo usar interpolación de strings usando strings de comillas dobles"


# Imprime a la salida estándar
puts "¡Estoy imprimiendo!"

# Variables
x = 25 #=> 25
x #=> 25

# Nota que la asignación retorna el valor asignado
# Esto significa que puedes hacer múltiples asignaciones:

x = y = 10 #=> 10
x #=> 10
y #=> 10

# Por convención, usa snake_case para nombres de variables
snake_case = true

# Usa nombres de variables descriptivos
ruta_para_la_raiz_de_un_projecto = '/buen/nombre/'
ruta = '/mal/nombre/'

# Los símbolos (son objetos)
# Los símbolos son inmutables, constantes reusables representadas internamente por un
# valor entero. Son normalmente usados en vez de strings para expresar eficientemente
# valores específicos y significativos

:pendiente.class #=> Symbol

status = :pendiente

status == :pendiente #=> true

status == 'pendiente' #=> false

status == :aprobado #=> false

# Arreglos

# Esto es un arreglo
arreglo = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]

# Arreglos pueden contener elementos de distintos tipos

[1, "hola", false] #=> => [1, "hola", false]

# Arreglos pueden ser indexados
# Desde el frente
arreglo[0] #=> 1
arreglo.first #=> 1
arreglo[12] #=> nil

# Al igual que en aritmética, el acceso como variable[índice]
# es sólo azúcar sintáctica
# para llamar el método [] de un objeto
arreglo.[] 0 #=> 1
arreglo.[] 12 #=> nil

# Desde el final
arreglo[-1] #=> 5
arreglo.last #=> 5

# Con un índice de inicio y longitud
arreglo[2, 3] #=> [3, 4, 5]

# Invertir un arreglo
a = [1, 2, 3]
a.reverse! #=> [3, 2, 1]

# O con rango
arreglo[1..3] #=> [2, 3, 4]

# Añade elementos a un arreglo así
arreglo << 6 #=> [1, 2, 3, 4, 5, 6]
# O así
arreglo.push(6) #=> [1, 2, 3, 4, 5, 6]

#Verifica si un elemento ya existe en ese arreglo
arreglo.include?(1) #=> true

# Hashes son los diccionarios principales de Ruby con pares llave/valor.
# Hashes se denotan con llaves:
hash = {'color' => 'verde', 'numero' => 5}

hash.keys #=> ['color', 'numero']

# Hashes pueden buscar rápidamente una llave:
hash['color'] #=> 'verde'
hash['numero'] #=> 5

# Preguntarle a un hash por una llave que no existe retorna 'nil':
hash['nada aqui'] #=> nil

# Desde Ruby 1.9, hay una sintaxis especial cuando se usa un símbolo como llave:

nuevo_hash = { defcon: 3, accion: true}

nuevo_hash.keys #=> [:defcon, :accion]

# Verifica la existencia de llaves y valores en el hash
new_hash.has_key?(:defcon) #=> true
new_hash.has_value?(3) #=> true

# Tip: Tanto los arreglos como los hashes son Enumerable (enumerables)
# Comparten muchos métodos útiles tales como 'each', 'map', 'count', y más

# Estructuras de Control

if true
  "declaracion 'if'"
elsif false
 "else if, opcional"
else
 "else, tambien opcional"
end

for contador in 1..5
  puts "iteracion #{contador}"
end
#=> iteracion 1
#=> iteracion 2
#=> iteracion 3
#=> iteracion 4
#=> iteracion 5

# SIN EMBARGO, nadie usa ciclos `for`
# En su lugar debes usar el método "each" y pasarle un block (bloque).
# Un bloque es un fragmento código que puedes pasar a métodos como `each`.
# Es símilar a las funciones lambda, funciones anónimas o `closures` en otros
# lenguajes de programación.
#
# El método `each` de un Range (rango) ejecuta el bloque una vez por cada elemento.
# Al bloque se le pasa un contador como parametro.
# Usar el método `each` con un bloque se ve así:

(1..5).each do |contador|
  puts "iteracion #{contador}"
end
#=> iteracion 1
#=> iteracion 2
#=> iteracion 3
#=> iteracion 4
#=> iteracion 5

# También puedes envolver el bloque entre llaves:
(1..5).each { |counter| puts "iteración #{contador}" }

#El contenido de las estructuras de datos en ruby puede ser iterado usando `each`.
arreglo.each do |elemento|
  puts "#{elemento} es parte del arreglo"
end
hash.each do |llave, valor|
  puts "#{llave} es #{valor}"
end

# Si aún necesitas un índice puedes usar "each_with_index" y definir una variable
# índice.
arreglo.each_with_index do |element, index|
  puts "#{element} tiene la posición #{index} en el arreglo"
end

contador = 1
while contador <= 5 do
  puts "iteracion #{contador}"
  contador += 1
end
#=> iteracion 1
#=> iteracion 2
#=> iteracion 3
#=> iteracion 4
#=> iteracion 5

# Hay una gran variedad de otras funciones iterativas útiles en Ruby,
# por ejemplo `map`, `reduce`,  `inject`, entre otras. Map, por ejemplo,
# toma el arreglo sobre el cuál está iterando, le hace cambios
# definidos en el bloque, y retorna un arreglo completamente nuevo.
arreglo = [1,2,3,4,5]
duplicado = array.map do |elemento|
  elemento * 2
end
puts duplicado
#=> [2,4,6,8,10]
puts array
#=> [1,2,3,4,5]

nota = 'B'

case nota
when 'A'
  puts "Muy bien muchacho"
when 'B'
  puts "Mejor suerte para la proxima"
when 'C'
  puts "Puedes hacerlo mejor"
when 'D'
  puts "Sobreviviendo"
when 'F'
  puts "¡Reprobaste!"
else
  puts "Sistema alternativo de notas, ¿eh?"
end
#=> "Mejor suerte para la proxima"

# Los casos también pueden usar rangos
nota = 82

case nota
when 90..100
  puts 'Excelente!'
when 80..100
  puts 'Buen trabajo'
else
  puts '¡Reprobaste!'
end
#=> "Buen trabajo"

# Manejo de excepciones
begin
  # código que podría causar excepción
  raise NoMemoryError, 'Se te acabó la memoria'
rescue NoMemoryError => variable_de_excepcion
  puts 'El error NoMemoryError ocurrió', variable_de_excepcion
rescue RuntimeError => otra_variable_de_excepcion
  puts 'El error RuntimeError ocurrió'
else
  puts 'Esto se ejecuta si ningun error ocurrió'
ensure
  puts 'Este código siempre se ejecuta, sin importar que'
end

# Funciones

def doble(x)
  x * 2
end

# Funciones (y todos los bloques) implícitamente retornan el valor de la última instrucción
doble(2) #=> 4

# Paréntesis son opcionales cuando el resultado no es ambiguo
doble 3 #=> 6

doble doble 3 #=> 12

def suma(x,y)
  x + y
end

# Arguméntos del método son separados por coma
suma 3, 4 #=> 7

suma suma(3,4), 5 #=> 12

# yield
# Todos los métodos tienen un parámetro bloque opcional e implícito
# puede llamarse con la palabra clave 'yield'

def alrededor
  puts "{"
  yield
  puts "}"
end

alrededor { puts 'hola mundo' }

# {
# hola mundo
# }

# Puedes pasar un bloque a una función
# '&' representa una referencia a un bloque
def visitantes(&bloque)
  bloque.call
end

# Puedes pasar una lista de argumentos, que serán convertidos en un arreglo
# Para eso sirve el operador ('*')
def visitantes(*arreglo)
  arreglo.each { |visitante| puts visitante }
end

# Define una clase con la palabra clave 'class'
class Humano

  # Una variable de clase. Es compartida por todas las instancias de la clase.
  @@species = "H. sapiens"

  # Inicializador Básico
  def initialize(nombre, edad=0)
    # Asigna el argumento a la variable de instancia 'nombre'
    @nombre = nombre
    # Si no dan edad, se usará el valor por defecto en la lista de argumentos.
    @edad = edad
  end

  # Método 'setter' (establecer) básico
  def nombre=(nombre)
    @nombre = nombre
  end

  # Método 'getter' (obtener) básico
  def nombre
    @nombre
  end

  # La funcionalidad anterior puede ser encapsulada usando el método attr_accessor
  # de la siguiente manera

  attr_accessor :name

  # Los métodos de tipo getter y setter también se pueden crear de manera individual
  # de la siguiente manera

  attr_reader :name
  attr_writer :name

  # Un método de clase usa 'self' (sí mismo) para distinguirse de métodos de instancia.
  # Sólo puede ser llamado en la clase, no por una instancia.
  def self.decir(mensaje)
    puts mensaje
  end

  def especie
    @@especie
  end
end


# Instancia una clase
jim = Humano.new("Jim Halpert")

dwight = Humano.new("Dwight K. Schrute")

# Llamemos un par de métodos
jim.especie #=> "H. sapiens"
jim.nombre #=> "Jim Halpert"
jim.nombre = "Jim Halpert II" #=> "Jim Halpert II"
jim.nombre #=> "Jim Halpert II"
dwight.especie #=> "H. sapiens"
dwight.nombre #=> "Dwight K. Schrute"

# Llama el método de clase
Humano.decir("Hi") #=> "Hi"

# El alcance de las variables es definido por la manera en que las nombramos.
# Las variables que inician con $ tienen un alcance global
$var = "Soy una variable global"
defined? $var #=> "global-variable"

# Las variables que empiezan con @ tienen un alcance de instancia
@var = "Soy una variable de instancia"
defined? @var #=> "instance-variable"

# Variables que empiezan con @@ tienen un alcance de clase
@@var = "Soy una variable de clase"
defined? @@var #=> "class variable"

# Las variables que empiezan con letra mayuscula son constantes
Var = "Soy una constante"
defined? Var #=> "constant"

# Las clases también son un objeto en ruby. Por lo cual, las clases también pueden tener variables de instancia.
# Variables de clase son compartidas a través de la clase y todos sus descendientes.

# clase base
class Humano
  @@foo = 0

  def self.foo
    @@foo
  end

  def self.foo=(valor)
    @@foo = valor
  end
end

# clase derivada
class Trabajador < Humano
end

Humano.foo # 0
Trabajador.foo # 0

Humano.foo = 2 # 2
Trabajador.foo # 2

# Las variables de instancia de la clase no son compartidas por los descendientes de la clase.

class Humano
  @bar = 0

  def self.bar
    @bar
  end

  def self.bar=(valor)
    @bar = valor
  end
end

class Doctor < Humano
end

Humano.bar # 0
Doctor.bar # nil

module ModuloEjemplo
  def foo
    'foo'
  end
end

# Al incluir un módulo sus métodos se comparten con las instancias de la clase
# Al extender un módulo sus métodos se comparten con la clase misma

class Persona
  include ModuloEjemplo
end

class Libro
  extend ModuloEjemplo
end

Persona.foo     # => NoMethodError: undefined method `foo' for Persona:Class
Persona.new.foo # => 'foo'
Libro.foo       # => 'foo'
Libro.new.foo   # => NoMethodError: undefined method `foo'

# Las llamadas de retorno (callbacks) son ejecutadas cuando se incluye o
# extiende un módulo
module EjemploConcern
  def self.incluido(base)
    base.extend(MetodosClase)
    base.send(:include, MetodosInstancia)
  end

  module MetodosClase
    def bar
      'bar'
    end
  end

  module MetodosInstancia
    def qux
      'qux'
    end
  end
end

class Algo
  include EjemploConcern
end

Algo.bar #=> 'bar'
Algo.qux #=> NoMethodError: undefined method `qux'
Algo.new.bar # => NoMethodError: undefined method `bar'
Algo.new.qux # => 'qux'
```

## Recursos adicionales
- [Aprende Ruby Mediante Ejemplo con Ejercicios](http://www.learneroo.com/modules/61/nodes/338) - Una variante de
esta referencia con ejercicios en navegador.
- [Documentación Oficial](http://www.ruby-doc.org/core-2.1.1/)
- [Ruby desde otros lenguajes](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
- [Programando Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - Una
[edición antigua](http://ruby-doc.com/docs/ProgrammingRuby/) gratuita disponible en línea.
- [Guía de estilo de Ruby](https://github.com/bbatsov/ruby-style-guide) - Guía de estilo creada por la comunidad.