-
Notifications
You must be signed in to change notification settings - Fork 0
/
getting_started.html
2211 lines (1991 loc) · 174 KB
/
getting_started.html
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
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Comenzando con Rails — Ruby on Rails Guides</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style-v2.css" data-turbo-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/print-v2.css" media="print">
<link rel="stylesheet" type="text/css" href="stylesheets/highlight-v2.css" data-turbo-track="reload">
<link rel="icon" href="images/favicon.ico" sizes="any">
<link rel="apple-touch-icon" href="images/icon.png">
<script src="javascripts/@hotwired--turbo.js" data-turbo-track="reload"></script>
<script src="javascripts/clipboard.js" data-turbo-track="reload"></script>
<script src="javascripts/guides.js" data-turbo-track="reload"></script>
<meta property="og:title" content="Comenzando con Rails — Ruby on Rails Guides" />
<meta name="description" content="NO LEA ESTE ARCHIVO EN GITHUB, LAS GUÍAS ESTÁN PUBLICADAS EN https://guides.rubyonrails.org.Comenzando con RailsEsta guía cubre cómo empezar y poner en marcha Ruby on Rails.Después de leer esta guía, sabrás: Cómo instalar Rails, crear una nueva aplicación Rails y conectar tu aplicación a una base de datos. La disposición general de una aplicación Rails. Los principios básicos de MVC (Modelo, Vista, Controlador) y diseño RESTful. Cómo generar rápidamente las piezas iniciales de una aplicación Rails." />
<meta property="og:description" content="NO LEA ESTE ARCHIVO EN GITHUB, LAS GUÍAS ESTÁN PUBLICADAS EN https://guides.rubyonrails.org.Comenzando con RailsEsta guía cubre cómo empezar y poner en marcha Ruby on Rails.Después de leer esta guía, sabrás: Cómo instalar Rails, crear una nueva aplicación Rails y conectar tu aplicación a una base de datos. La disposición general de una aplicación Rails. Los principios básicos de MVC (Modelo, Vista, Controlador) y diseño RESTful. Cómo generar rápidamente las piezas iniciales de una aplicación Rails." />
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="Ruby on Rails Guides" />
<meta property="og:image" content="https://avatars.githubusercontent.com/u/4223" />
<meta property="og:type" content="website" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:[email protected]&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Heebo:[email protected]&family=Noto+Sans+Arabic:[email protected]&display=swap" rel="stylesheet">
<meta name="theme-color" content="#C81418">
</head>
<body class="guide">
<nav id="topNav" aria-label="Secondary">
<div class="wrapper">
<strong class="more-info-label">Más en <a href="https://rubyonrails.org/">rubyonrails.org:</a> </strong>
<span class="red-button more-info-button">
Más Ruby on Rails
</span>
<ul class="more-info-links s-hidden">
<li class="more-info"><a href="https://rubyonrails.org/blog">Blog</a></li>
<li class="more-info"><a href="https://guides.rubyonrails.org/">Guías</a></li>
<li class="more-info"><a href="https://api.rubyonrails.org/">API</a></li>
<li class="more-info"><a href="https://discuss.rubyonrails.org/">Foro</a></li>
<li class="more-info"><a href="https://github.com/rails/rails">Contribuir en GitHub</a></li>
</ul>
</div>
</nav>
<header id="page_header">
<div class="wrapper clearfix">
<nav id="feature_nav">
<div class="header-logo">
<a href="index.html" title="Regresar a la página principal de Guías para Edge">Guías</a>
<span id="version_switcher">
Versión:
<select class="guides-version">
<option value="https://edgeguides.rubyonrails.org/" selected>Edge</option>
<option value="https://guides.rubyonrails.org/v7.2/">7.2</option>
<option value="https://guides.rubyonrails.org/v7.1/">7.1</option>
<option value="https://guides.rubyonrails.org/v7.0/">7.0</option>
<option value="https://guides.rubyonrails.org/v6.1/">6.1</option>
<option value="https://guides.rubyonrails.org/v6.0/">6.0</option>
<option value="https://guides.rubyonrails.org/v5.2/">5.2</option>
<option value="https://guides.rubyonrails.org/v5.1/">5.1</option>
<option value="https://guides.rubyonrails.org/v5.0/">5.0</option>
<option value="https://guides.rubyonrails.org/v4.2/">4.2</option>
<option value="https://guides.rubyonrails.org/v4.1/">4.1</option>
<option value="https://guides.rubyonrails.org/v4.0/">4.0</option>
<option value="https://guides.rubyonrails.org/v3.2/">3.2</option>
<option value="https://guides.rubyonrails.org/v3.1/">3.1</option>
<option value="https://guides.rubyonrails.org/v3.0/">3.0</option>
<option value="https://guides.rubyonrails.org/v2.3/">2.3</option>
</select>
</span>
</div>
<ul class="nav">
<li><a class="nav-item" id="home_nav" href="https://rubyonrails.org/">Inicio</a></li>
<li class="guides-index guides-index-large">
<a href="index.html" id="guidesMenu" class="guides-index-item nav-item">Índice de Guías</a>
<div id="guides" class="clearfix" style="display: none;">
<hr />
<dl class="guides-section-container">
<div class="guides-section">
<dt>Comienza Aquí</dt>
<dd><a href="getting_started.html">Primeros Pasos con Rails</a></dd>
</div>
<div class="guides-section">
<dt>Modelos</dt>
<dd><a href="active_record_basics.html">Conceptos Básicos de Active Record</a></dd>
<dd><a href="active_record_migrations.html">Migraciones de Active Record</a></dd>
<dd><a href="active_record_validations.html">Validaciones de Active Record</a></dd>
</div>
<div class="guides-section">
<dt>Vistas</dt>
<dd><a href="action_view_overview.html">Resumen de Action View</a></dd>
<dd><a href="layouts_and_rendering.html">Diseños y Renderizado en Rails</a></dd>
</div>
<div class="guides-section">
<dt>Controladores</dt>
<dd><a href="action_controller_overview.html">Resumen de Action Controller</a></dd>
<dd><a href="routing.html">Enrutamiento en Rails desde el Exterior</a></dd>
</div>
<div class="guides-section">
<dt>Otros Componentes</dt>
<dd><a href="active_support_core_extensions.html">Extensiones Básicas de Active Support</a></dd>
<dd><a href="action_mailer_basics.html">Conceptos Básicos de Action Mailer</a></dd>
<dd><a href="action_mailbox_basics.html">Conceptos Básicos de Action Mailbox</a></dd>
<dd><a href="action_text_overview.html">Resumen de Action Text</a></dd>
<dd><a href="active_job_basics.html">Conceptos Básicos de Active Job</a></dd>
</div>
<div class="guides-section">
<dt>Políticas</dt>
<dd><a href="maintenance_policy.html">Política de Mantenimiento</a></dd>
</div>
<div class="guides-section">
<dt>Notas de Lanzamiento</dt>
<dd><a href="upgrading_ruby_on_rails.html">Actualizando Ruby on Rails</a></dd>
<dd><a href="7_2_release_notes.html">Versión 7.2 - ?</a></dd>
<dd><a href="7_1_release_notes.html">Versión 7.1 - Octubre 2023</a></dd>
<dd><a href="7_0_release_notes.html">Versión 7.0 - Diciembre 2021</a></dd>
<dd><a href="6_1_release_notes.html">Versión 6.1 - Diciembre 2020</a></dd>
</div>
</dl>
</div>
</li>
<li><a class="nav-item" href="contributing_to_ruby_on_rails.html">Contribuir</a></li>
<li class="guides-index guides-index-small">
<select class="guides-index-item nav-item">
<option value="index.html">Índice de Guías</option>
<optgroup label="Comienza Aquí">
<option value="getting_started.html">Primeros Pasos con Rails</option>
</optgroup>
<optgroup label="Modelos">
<option value="active_record_basics.html">Conceptos Básicos de Active Record</option>
<option value="active_record_migrations.html">Migraciones de Active Record</option>
<option value="active_record_validations.html">Validaciones de Active Record</option>
</optgroup>
<optgroup label="Vistas">
<option value="action_view_overview.html">Resumen de Action View</option>
<option value="layouts_and_rendering.html">Diseños y Renderizado en Rails</option>
</optgroup>
<optgroup label="Controladores">
<option value="action_controller_overview.html">Resumen de Action Controller</option>
<option value="routing.html">Enrutamiento en Rails desde el Exterior</option>
</optgroup>
<optgroup label="Otros Componentes">
<option value="active_support_core_extensions.html">Extensiones Básicas de Active Support</option>
<option value="action_mailer_basics.html">Conceptos Básicos de Action Mailer</option>
<option value="action_mailbox_basics.html">Conceptos Básicos de Action Mailbox</option>
<option value="action_text_overview.html">Resumen de Action Text</option>
<option value="active_job_basics.html">Conceptos Básicos de Active Job</option>
</optgroup>
<optgroup label="Políticas">
<option value="maintenance_policy.html">Política de Mantenimiento</option>
</optgroup>
<optgroup label="Notas de Lanzamiento">
<option value="upgrading_ruby_on_rails.html">Actualizando Ruby on Rails</option>
<option value="7_2_release_notes.html">Versión 7.2 - ?</option>
<option value="7_1_release_notes.html">Versión 7.1 - Octubre 2023</option>
<option value="7_0_release_notes.html">Versión 7.0 - Diciembre 2021</option>
<option value="6_1_release_notes.html">Versión 6.1 - Diciembre 2020</option>
</optgroup>
</select>
</li>
</ul>
</nav>
</div>
</header>
<hr class="hide" />
<section id="feature">
<div class="wrapper">
<p><strong>NO LEA ESTE ARCHIVO EN GITHUB, LAS GUÍAS ESTÁN PUBLICADAS EN <a href="https://guides.rubyonrails.org">https://guides.rubyonrails.org</a>.</strong></p><h1>Comenzando con Rails</h1><p>Esta guía cubre cómo empezar y poner en marcha Ruby on Rails.</p><p>Después de leer esta guía, sabrás:</p>
<ul>
<li>Cómo instalar Rails, crear una nueva aplicación Rails y conectar tu aplicación a una base de datos.</li>
<li>La disposición general de una aplicación Rails.</li>
<li>Los principios básicos de MVC (Modelo, Vista, Controlador) y diseño RESTful.</li>
<li>Cómo generar rápidamente las piezas iniciales de una aplicación Rails.</li>
</ul>
<nav id="subCol">
<h3 class="chapter">
<picture>
<!-- Using the `source` HTML tag to set the dark theme image -->
<source
srcset="images/icon_book-close-bookmark-1-wht.svg"
media="(prefers-color-scheme: dark)"
/>
<img src="images/icon_book-close-bookmark-1.svg" alt="Chapter Icon" />
</picture>
Chapters
</h3>
<ol class="chapters">
<li><a href="#supuestos-de-la-guía">Supuestos de la Guía</a></li>
<li><a href="#¿qué-es-rails-questionmark">¿Qué es Rails?</a></li>
<li><a href="#creando-un-nuevo-proyecto-rails">Creando un Nuevo Proyecto Rails</a>
<ul>
<li><a href="#creando-un-nuevo-proyecto-rails-instalando-rails">Instalando Rails</a></li>
<li><a href="#creando-la-aplicación-blog">Creando la Aplicación Blog</a></li>
</ul></li>
<li><a href="#¡hola-rails-bang">¡Hola, Rails!</a>
<ul>
<li><a href="#iniciando-el-servidor-web">Iniciando el Servidor Web</a></li>
<li><a href="#di-hola-rails">Di "Hola", Rails</a></li>
<li><a href="#configurando-la-página-de-inicio-de-la-aplicación">Configurando la Página de Inicio de la Aplicación</a></li>
</ul></li>
<li><a href="#carga-automática">Carga Automática</a></li>
<li><a href="#mvc-y-tú">MVC y Tú</a>
<ul>
<li><a href="#mvc-y-tú-generando-un-modelo">Generando un Modelo</a></li>
<li><a href="#migraciones-de-base-de-datos">Migraciones de Base de Datos</a></li>
<li><a href="#usando-un-modelo-para-interactuar-con-la-base-de-datos">Usando un Modelo para Interactuar con la Base de Datos</a></li>
<li><a href="#mostrando-una-lista-de-artículos">Mostrando una Lista de Artículos</a></li>
</ul></li>
<li><a href="#crudit-donde-crudit-es-debido">CRUDit Donde CRUDit es Debido</a>
<ul>
<li><a href="#mostrando-un-solo-artículo">Mostrando un Solo Artículo</a></li>
<li><a href="#enrutamiento-de-recursos">Enrutamiento de Recursos</a></li>
<li><a href="#creando-un-nuevo-artículo">Creando un Nuevo Artículo</a></li>
<li><a href="#actualizando-un-artículo">Actualizando un Artículo</a></li>
<li><a href="#eliminando-un-artículo">Eliminando un Artículo</a></li>
</ul></li>
<li><a href="#agregando-un-segundo-modelo">Agregando un Segundo Modelo</a>
<ul>
<li><a href="#agregando-un-segundo-modelo-generando-un-modelo">Generando un Modelo</a></li>
<li><a href="#asociando-modelos">Asociando Modelos</a></li>
<li><a href="#agregando-una-ruta-para-comentarios">Agregando una Ruta para Comentarios</a></li>
<li><a href="#generando-un-controlador">Generando un Controlador</a></li>
</ul></li>
<li><a href="#refactorización">Refactorización</a>
<ul>
<li><a href="#renderizando-colecciones-parciales">Renderizando Colecciones Parciales</a></li>
<li><a href="#renderizando-un-formulario-parcial">Renderizando un Formulario Parcial</a></li>
<li><a href="#usando-concerns">Usando Concerns</a></li>
</ul></li>
</ol>
</nav>
<hr>
</div>
</section>
<main id="container">
<div class="wrapper">
<div id="mainCol">
<h2 id="supuestos-de-la-guía"><a class="anchorlink" href="#supuestos-de-la-guía"><span>1</span> Supuestos de la Guía</a></h2><p>Esta guía está diseñada para principiantes que quieren comenzar a crear una aplicación Rails desde cero. No se asume que tengas experiencia previa con Rails.</p><p>Rails es un marco de aplicación web que se ejecuta en el lenguaje de programación Ruby. Si no tienes experiencia previa con Ruby, encontrarás una curva de aprendizaje muy pronunciada al sumergirte directamente en Rails. Hay varias listas curadas de recursos en línea para aprender Ruby:</p>
<ul>
<li><a href="https://www.ruby-lang.org/en/documentation/">Sitio web oficial del lenguaje de programación Ruby</a></li>
<li><a href="https://github.com/EbookFoundation/free-programming-books/blob/master/books/free-programming-books-langs.md#ruby">Lista de Libros de Programación Gratuitos</a></li>
</ul>
<p>Ten en cuenta que algunos recursos, aunque todavía son excelentes, cubren versiones más antiguas de Ruby, y pueden no incluir algunas sintaxis que verás en el desarrollo diario con Rails.</p><h2 id="¿qué-es-rails-questionmark"><a class="anchorlink" href="#¿qué-es-rails-questionmark"><span>2</span> ¿Qué es Rails?</a></h2><p>Rails es un marco de desarrollo de aplicaciones web escrito en el lenguaje de programación Ruby. Está diseñado para hacer que la programación de aplicaciones web sea más fácil al hacer suposiciones sobre lo que cada desarrollador necesita para comenzar. Te permite escribir menos código mientras logras más que muchos otros lenguajes y marcos. Los desarrolladores experimentados en Rails también informan que hace que el desarrollo de aplicaciones web sea más divertido.</p><p>Rails es un software con opiniones. Hace la suposición de que hay una "mejor" manera de hacer las cosas, y está diseñado para fomentar esa manera - y en algunos casos para desalentar alternativas. Si aprendes "La Manera Rails" probablemente descubrirás un tremendo aumento en la productividad. Si persistes en traer viejos hábitos de otros lenguajes a tu desarrollo en Rails, y tratas de usar patrones que aprendiste en otro lugar, puedes tener una experiencia menos feliz.</p><p>La filosofía de Rails incluye dos principios rectores principales:</p>
<ul>
<li><strong>No te Repitas:</strong> DRY es un principio de desarrollo de software que establece que "Cada pieza de conocimiento debe tener una representación única, inequívoca y autorizada dentro de un sistema". Al no escribir la misma información una y otra vez, nuestro código es más mantenible, más extensible y menos propenso a errores.</li>
<li><strong>Convención sobre Configuración:</strong> Rails tiene opiniones sobre la mejor manera de hacer muchas cosas en una aplicación web, y por defecto a este conjunto de convenciones, en lugar de requerir que especifiques minucias a través de interminables archivos de configuración.</li>
</ul>
<h2 id="creando-un-nuevo-proyecto-rails"><a class="anchorlink" href="#creando-un-nuevo-proyecto-rails"><span>3</span> Creando un Nuevo Proyecto Rails</a></h2><p>CONSEJO: Las nuevas aplicaciones Rails vienen con un entorno de desarrollo Dev Container preconfigurado. Esta es la forma más rápida de comenzar con Rails. Para instrucciones, consulta <a href="getting_started_with_devcontainer.html">Comenzando con Dev Containers</a></p><p>La mejor manera de leer esta guía es seguirla paso a paso. Todos los pasos son esenciales para ejecutar esta aplicación de ejemplo y no se necesita código o pasos adicionales.</p><p>Siguiendo esta guía, crearás un proyecto Rails llamado <code>blog</code>, un weblog (muy) simple. Antes de que puedas comenzar a construir la aplicación, necesitas asegurarte de que tienes Rails instalado.</p><p>NOTA: Los ejemplos a continuación usan <code>$</code> para representar tu terminal en un sistema operativo tipo UNIX, aunque puede haber sido personalizado para aparecer de manera diferente. Si estás usando Windows, tu terminal se verá algo así como <code>C:\source_code></code>.</p><h3 id="creando-un-nuevo-proyecto-rails-instalando-rails"><a class="anchorlink" href="#creando-un-nuevo-proyecto-rails-instalando-rails"><span>3.1</span> Instalando Rails</a></h3><p>Antes de instalar Rails, debes verificar que tu sistema tenga los prerrequisitos adecuados instalados. Estos incluyen:</p>
<ul>
<li>Ruby</li>
<li>SQLite3</li>
</ul>
<h4 id="instalando-ruby"><a class="anchorlink" href="#instalando-ruby"><span>3.1.1</span> Instalando Ruby</a></h4><p>Abre un terminal. En macOS abre Terminal.app; en Windows elige "Ejecutar" desde tu menú de Inicio y escribe <code>cmd.exe</code>. Cualquier comando precedido por un signo de dólar <code>$</code> debe ejecutarse en la línea de comandos. Verifica que tengas una versión actual de Ruby instalada:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">ruby</span> <span class="nt">--version</span>
<span class="go">ruby 3.1.0
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="ruby --version
">Copy</button>
</div>
<p>Rails requiere Ruby versión 3.1.0 o posterior. Se prefiere usar la última versión de Ruby. Si el número de versión devuelto es menor a ese número (como 2.3.7, o 1.8.7), necesitarás instalar una copia nueva de Ruby.</p><p>Para instalar Rails en Windows, primero necesitarás instalar <a href="https://rubyinstaller.org/">Ruby Installer</a>.</p><p>Para más métodos de instalación para la mayoría de los sistemas operativos, echa un vistazo a <a href="https://www.ruby-lang.org/en/documentation/installation/">ruby-lang.org</a>.</p><h4 id="instalando-sqlite3"><a class="anchorlink" href="#instalando-sqlite3"><span>3.1.2</span> Instalando SQLite3</a></h4><p>También necesitarás una instalación de la base de datos SQLite3. Muchos sistemas operativos tipo UNIX populares vienen con una versión aceptable de SQLite3. Otros pueden encontrar instrucciones de instalación en el <a href="https://www.sqlite.org">sitio web de SQLite3</a>.</p><p>Verifica que esté correctamente instalado y en tu <code>PATH</code> de carga:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">sqlite3</span> <span class="nt">--version</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="sqlite3 --version
">Copy</button>
</div>
<p>El programa debería informar su versión.</p><h4 id="creando-un-nuevo-proyecto-rails-instalando-rails-instalando-rails"><a class="anchorlink" href="#creando-un-nuevo-proyecto-rails-instalando-rails-instalando-rails"><span>3.1.3</span> Instalando Rails</a></h4><p>Para instalar Rails, usa el comando <code>gem install</code> proporcionado por RubyGems:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">gem install rails</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="gem install rails
">Copy</button>
</div>
<p>Para verificar que tienes todo instalado correctamente, deberías poder ejecutar lo siguiente en una nueva terminal:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">rails</span> <span class="nt">--version</span>
<span class="go">Rails 7.2.0
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="rails --version
">Copy</button>
</div>
<p>Si dice algo como "Rails 7.2.0", estás listo para continuar.</p><h3 id="creando-la-aplicación-blog"><a class="anchorlink" href="#creando-la-aplicación-blog"><span>3.2</span> Creando la Aplicación Blog</a></h3><p>Rails viene con una serie de scripts llamados generadores que están diseñados para hacer tu vida de desarrollo más fácil al crear todo lo necesario para comenzar a trabajar en una tarea particular. Uno de estos es el generador de nuevas aplicaciones, que te proporcionará la base de una nueva aplicación Rails para que no tengas que escribirla tú mismo.</p><p>Para usar este generador, abre una terminal, navega a un directorio donde tengas derechos para crear archivos y ejecuta:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">rails </span>new blog
</code></pre>
<button class="clipboard-button" data-clipboard-text="rails new blog
">Copy</button>
</div>
<p>Esto creará una aplicación Rails llamada Blog en un directorio <code>blog</code> e instalará las dependencias de gemas que ya están mencionadas en <code>Gemfile</code> usando <code>bundle install</code>.</p><p>CONSEJO: Puedes ver todas las opciones de línea de comandos que el generador de aplicaciones Rails acepta ejecutando <code>rails new --help</code>.</p><p>Después de crear la aplicación blog, cambia a su carpeta:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">cd </span>blog
</code></pre>
<button class="clipboard-button" data-clipboard-text="cd blog
">Copy</button>
</div>
<p>El directorio <code>blog</code> tendrá una serie de archivos y carpetas generados que constituyen la estructura de una aplicación Rails. La mayor parte del trabajo en este tutorial ocurrirá en la carpeta <code>app</code>, pero aquí hay un resumen básico de la función de cada uno de los archivos y carpetas que Rails crea por defecto:</p>
<table><thead>
<tr>
<th>Archivo/Carpeta</th>
<th>Propósito</th>
</tr>
</thead><tbody>
<tr>
<td>app/</td>
<td>Contiene los controladores, modelos, vistas, ayudantes, mailers, canales, trabajos y activos para tu aplicación. Te enfocarás en esta carpeta para el resto de esta guía.</td>
</tr>
<tr>
<td>bin/</td>
<td>Contiene el script <code>rails</code> que inicia tu aplicación y puede contener otros scripts que usas para configurar, actualizar, desplegar o ejecutar tu aplicación.</td>
</tr>
<tr>
<td>config/</td>
<td>Contiene la configuración para las rutas de tu aplicación, base de datos y más. Esto se cubre en más detalle en <a href="configuring.html">Configurando Aplicaciones Rails</a>.</td>
</tr>
<tr>
<td>config.ru</td>
<td>Configuración de Rack para servidores basados en Rack usados para iniciar la aplicación. Para más información sobre Rack, consulta el <a href="https://rack.github.io/">sitio web de Rack</a>.</td>
</tr>
<tr>
<td>db/</td>
<td>Contiene tu esquema actual de base de datos, así como las migraciones de base de datos.</td>
</tr>
<tr>
<td>Dockerfile</td>
<td>Archivo de configuración para Docker.</td>
</tr>
<tr>
<td>Gemfile<br>Gemfile.lock</td>
<td>Estos archivos te permiten especificar qué dependencias de gemas son necesarias para tu aplicación Rails. Estos archivos son usados por la gema Bundler. Para más información sobre Bundler, consulta el <a href="https://bundler.io">sitio web de Bundler</a>.</td>
</tr>
<tr>
<td>lib/</td>
<td>Módulos extendidos para tu aplicación.</td>
</tr>
<tr>
<td>log/</td>
<td>Archivos de registro de la aplicación.</td>
</tr>
<tr>
<td>public/</td>
<td>Contiene archivos estáticos y activos compilados. Cuando tu aplicación está en ejecución, este directorio será expuesto tal cual.</td>
</tr>
<tr>
<td>Rakefile</td>
<td>Este archivo localiza y carga tareas que pueden ser ejecutadas desde la línea de comandos. Las definiciones de tareas están definidas a lo largo de los componentes de Rails. En lugar de cambiar <code>Rakefile</code>, deberías agregar tus propias tareas añadiendo archivos al directorio <code>lib/tasks</code> de tu aplicación.</td>
</tr>
<tr>
<td>README.md</td>
<td>Este es un breve manual de instrucciones para tu aplicación. Deberías editar este archivo para decirle a otros qué hace tu aplicación, cómo configurarla, etc.</td>
</tr>
<tr>
<td>storage/</td>
<td>Archivos de Active Storage para el Servicio de Disco. Esto se cubre en <a href="active_storage_overview.html">Descripción General de Active Storage</a>.</td>
</tr>
<tr>
<td>test/</td>
<td>Pruebas unitarias, fixtures y otros aparatos de prueba. Estos se cubren en <a href="testing.html">Pruebas de Aplicaciones Rails</a>.</td>
</tr>
<tr>
<td>tmp/</td>
<td>Archivos temporales (como archivos de caché y pid).</td>
</tr>
<tr>
<td>vendor/</td>
<td>Un lugar para todo el código de terceros. En una aplicación Rails típica esto incluye gemas vendidas.</td>
</tr>
<tr>
<td>.dockerignore</td>
<td>Este archivo le dice a Docker qué archivos no debería copiar en el contenedor.</td>
</tr>
<tr>
<td>.gitattributes</td>
<td>Este archivo define metadatos para rutas específicas en un repositorio git. Estos metadatos pueden ser usados por git y otras herramientas para mejorar su comportamiento. Consulta la <a href="https://git-scm.com/docs/gitattributes">documentación de gitattributes</a> para más información.</td>
</tr>
<tr>
<td>.github/</td>
<td>Contiene archivos específicos de GitHub.</td>
</tr>
<tr>
<td>.gitignore</td>
<td>Este archivo le dice a git qué archivos (o patrones) debería ignorar. Consulta <a href="https://help.github.com/articles/ignoring-files">GitHub - Ignorando archivos</a> para más información sobre ignorar archivos.</td>
</tr>
<tr>
<td>.rubocop.yml</td>
<td>Este archivo contiene la configuración para RuboCop.</td>
</tr>
<tr>
<td>.ruby-version</td>
<td>Este archivo contiene la versión predeterminada de Ruby.</td>
</tr>
</tbody></table>
<h2 id="¡hola-rails-bang"><a class="anchorlink" href="#¡hola-rails-bang"><span>4</span> ¡Hola, Rails!</a></h2><p>Para empezar, pongamos algo de texto en pantalla rápidamente. Para hacer esto, necesitas poner en marcha el servidor de tu aplicación Rails.</p><h3 id="iniciando-el-servidor-web"><a class="anchorlink" href="#iniciando-el-servidor-web"><span>4.1</span> Iniciando el Servidor Web</a></h3><p>En realidad, ya tienes una aplicación Rails funcional. Para verla, necesitas iniciar un servidor web en tu máquina de desarrollo. Puedes hacerlo ejecutando el siguiente comando en el directorio <code>blog</code>:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>server
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails server
">Copy</button>
</div>
<p>CONSEJO: Si estás usando Windows, debes pasar los scripts bajo la carpeta <code>bin</code> directamente al intérprete de Ruby, por ejemplo, <code>ruby bin\rails server</code>.</p><p>CONSEJO: La compresión de activos JavaScript requiere que tengas un entorno de ejecución de JavaScript disponible en tu sistema, en ausencia de un entorno de ejecución verás un error <code>execjs</code> durante la compresión de activos. Por lo general, macOS y Windows vienen con un entorno de ejecución de JavaScript instalado. <code>therubyrhino</code> es el entorno de ejecución recomendado para usuarios de JRuby y se agrega por defecto al <code>Gemfile</code> en aplicaciones generadas bajo JRuby. Puedes investigar todos los entornos de ejecución compatibles en <a href="https://github.com/rails/execjs#readme">ExecJS</a>.</p><p>Esto pondrá en marcha Puma, un servidor web distribuido con Rails por defecto. Para ver tu aplicación en acción, abre una ventana de navegador y navega a <a href="http://localhost:3000">http://localhost:3000</a>. Deberías ver la página de información predeterminada de Rails:</p><p><img src="images/getting_started/rails_welcome.png" alt="Captura de pantalla de la página de inicio de Rails"></p><p>Cuando quieras detener el servidor web, presiona Ctrl+C en la ventana del terminal donde está en ejecución. En el entorno de desarrollo, Rails generalmente no requiere que reinicies el servidor; los cambios que realices en los archivos serán recogidos automáticamente por el servidor.</p><p>La página de inicio de Rails es la <em>prueba de humo</em> para una nueva aplicación Rails: asegura que tienes tu software configurado correctamente para servir una página.</p><h3 id="di-hola-rails"><a class="anchorlink" href="#di-hola-rails"><span>4.2</span> Di "Hola", Rails</a></h3><p>Para que Rails diga "Hola", necesitas crear al menos una <em>ruta</em>, un <em>controlador</em> con una <em>acción</em> y una <em>vista</em>. Una ruta mapea una solicitud a una acción de controlador. Una acción de controlador realiza el trabajo necesario para manejar la solicitud y prepara cualquier dato para la vista. Una vista muestra datos en un formato deseado.</p><p>En términos de implementación: Las rutas son reglas escritas en un <a href="https://es.wikipedia.org/wiki/Lenguaje_de_dominios_espec%C3%ADficos">DSL (Lenguaje Específico de Dominio)</a> en Ruby. Los controladores son clases Ruby, y sus métodos públicos son acciones. Y las vistas son plantillas, generalmente escritas en una mezcla de HTML y Ruby.</p><p>Comencemos agregando una ruta a nuestro archivo de rutas, <code>config/routes.rb</code>, en la parte superior del bloque <code>Rails.application.routes.draw</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
<span class="n">get</span> <span class="s2">"/articles"</span><span class="p">,</span> <span class="ss">to: </span><span class="s2">"articles#index"</span>
<span class="c1"># Para detalles sobre el DSL disponible dentro de este archivo, consulta https://guides.rubyonrails.org/routing.html</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Rails.application.routes.draw do
get "/articles", to: "articles#index"
# Para detalles sobre el DSL disponible dentro de este archivo, consulta https://guides.rubyonrails.org/routing.html
end
">Copy</button>
</div>
<p>La ruta anterior declara que las solicitudes <code>GET /articles</code> se mapean a la acción <code>index</code> de <code>ArticlesController</code>.</p><p>Para crear <code>ArticlesController</code> y su acción <code>index</code>, ejecutaremos el generador de controladores (con la opción <code>--skip-routes</code> porque ya tenemos una ruta adecuada):</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>generate controller Articles index <span class="nt">--skip-routes</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails generate controller Articles index --skip-routes
">Copy</button>
</div>
<p>Rails creará varios archivos para ti:</p><div class="interstitial code">
<pre><code class="highlight plaintext">create app/controllers/articles_controller.rb
invoke erb
create app/views/articles
create app/views/articles/index.html.erb
invoke test_unit
create test/controllers/articles_controller_test.rb
invoke helper
create app/helpers/articles_helper.rb
invoke test_unit
</code></pre>
<button class="clipboard-button" data-clipboard-text="create app/controllers/articles_controller.rb
invoke erb
create app/views/articles
create app/views/articles/index.html.erb
invoke test_unit
create test/controllers/articles_controller_test.rb
invoke helper
create app/helpers/articles_helper.rb
invoke test_unit
">Copy</button>
</div>
<p>El más importante de estos es el archivo de controlador, <code>app/controllers/articles_controller.rb</code>. Echemos un vistazo:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ArticlesController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">index</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ArticlesController < ApplicationController
def index
end
end
">Copy</button>
</div>
<p>La acción <code>index</code> está vacía. Cuando una acción no renderiza explícitamente una vista (o de otra manera desencadena una respuesta HTTP), Rails renderizará automáticamente una vista que coincida con el nombre del controlador y la acción. ¡Convención sobre Configuración! Las vistas se encuentran en el directorio <code>app/views</code>. Así que la acción <code>index</code> renderizará <code>app/views/articles/index.html.erb</code> por defecto.</p><p>Abramos <code>app/views/articles/index.html.erb</code>, y reemplacemos su contenido con:</p><div class="interstitial code">
<pre><code class="highlight html"><span class="nt"><h1></span>¡Hola, Rails!<span class="nt"></h1></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>¡Hola, Rails!</h1>
">Copy</button>
</div>
<p>Si previamente detuviste el servidor web para ejecutar el generador de controladores, reinícialo con <code>bin/rails server</code>. Ahora visita <a href="http://localhost:3000/articles">http://localhost:3000/articles</a>, ¡y ve nuestro texto mostrado!</p><h3 id="configurando-la-página-de-inicio-de-la-aplicación"><a class="anchorlink" href="#configurando-la-página-de-inicio-de-la-aplicación"><span>4.3</span> Configurando la Página de Inicio de la Aplicación</a></h3><p>En este momento, <a href="http://localhost:3000">http://localhost:3000</a> todavía muestra una página con el logo de Ruby on Rails. Vamos a mostrar nuestro texto "¡Hola, Rails!" en <a href="http://localhost:3000">http://localhost:3000</a> también. Para hacerlo, agregaremos una ruta que mapee el <em>camino raíz</em> de nuestra aplicación al controlador y acción apropiados.</p><p>Abramos <code>config/routes.rb</code>, y agreguemos la siguiente ruta <code>root</code> en la parte superior del bloque <code>Rails.application.routes.draw</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
<span class="n">root</span> <span class="s2">"articles#index"</span>
<span class="n">get</span> <span class="s2">"/articles"</span><span class="p">,</span> <span class="ss">to: </span><span class="s2">"articles#index"</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Rails.application.routes.draw do
root "articles#index"
get "/articles", to: "articles#index"
end
">Copy</button>
</div>
<p>Ahora podemos ver nuestro texto "¡Hola, Rails!" cuando visitamos <a href="http://localhost:3000">http://localhost:3000</a>, confirmando que la ruta <code>root</code> también está mapeada a la acción <code>index</code> de <code>ArticlesController</code>.</p><p>CONSEJO: Para aprender más sobre enrutamiento, consulta <a href="routing.html">Enrutamiento de Rails desde el Exterior hacia Adentro</a>.</p><h2 id="carga-automática"><a class="anchorlink" href="#carga-automática"><span>5</span> Carga Automática</a></h2><p>Las aplicaciones Rails <strong>no</strong> usan <code>require</code> para cargar el código de la aplicación.</p><p>Puedes haber notado que <code>ArticlesController</code> hereda de <code>ApplicationController</code>, pero <code>app/controllers/articles_controller.rb</code> no tiene nada como</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">require</span> <span class="s2">"application_controller"</span> <span class="c1"># NO HAGAS ESTO.</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="require "application_controller" # NO HAGAS ESTO.
">Copy</button>
</div>
<p>Las clases y módulos de la aplicación están disponibles en todas partes, no necesitas y <strong>no deberías</strong> cargar nada bajo <code>app</code> con <code>require</code>. Esta característica se llama <em>carga automática</em>, y puedes aprender más sobre ella en <a href="autoloading_and_reloading_constants.html"><em>Carga y Recarga Automática de Constantes</em></a>.</p><p>Solo necesitas llamadas <code>require</code> para dos casos de uso:</p>
<ul>
<li>Para cargar archivos bajo el directorio <code>lib</code>.</li>
<li>Para cargar dependencias de gemas que tienen <code>require: false</code> en el <code>Gemfile</code>.</li>
</ul>
<h2 id="mvc-y-tú"><a class="anchorlink" href="#mvc-y-tú"><span>6</span> MVC y Tú</a></h2><p>Hasta ahora, hemos discutido rutas, controladores, acciones y vistas. Todas estas son piezas típicas de una aplicación web que sigue el patrón <a href="https://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador">MVC (Modelo-Vista-Controlador)</a>. MVC es un patrón de diseño que divide las responsabilidades de una aplicación para hacerla más fácil de razonar. Rails sigue este patrón de diseño por convención.</p><p>Dado que tenemos un controlador y una vista para trabajar, generemos la siguiente pieza: un modelo.</p><h3 id="mvc-y-tú-generando-un-modelo"><a class="anchorlink" href="#mvc-y-tú-generando-un-modelo"><span>6.1</span> Generando un Modelo</a></h3><p>Un <em>modelo</em> es una clase Ruby que se utiliza para representar datos. Además, los modelos pueden interactuar con la base de datos de la aplicación a través de una característica de Rails llamada <em>Active Record</em>.</p><p>Para definir un modelo, usaremos el generador de modelos:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>generate model Article title:string body:text
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails generate model Article title:string body:text
">Copy</button>
</div>
<p>NOTA: Los nombres de los modelos son <strong>singulares</strong>, porque un modelo instanciado representa un solo registro de datos. Para ayudar a recordar esta convención, piensa en cómo llamarías al constructor del modelo: queremos escribir <code>Article.new(...)</code>, <strong>no</strong> <code>Articles.new(...)</code>.</p><p>Esto creará varios archivos:</p><div class="interstitial code">
<pre><code class="highlight plaintext">invoke active_record
create db/migrate/<timestamp>_create_articles.rb
create app/models/article.rb
invoke test_unit
create test/models/article_test.rb
create test/fixtures/articles.yml
</code></pre>
<button class="clipboard-button" data-clipboard-text="invoke active_record
create db/migrate/<timestamp>_create_articles.rb
create app/models/article.rb
invoke test_unit
create test/models/article_test.rb
create test/fixtures/articles.yml
">Copy</button>
</div>
<p>Los dos archivos en los que nos centraremos son el archivo de migración (<code>db/migrate/<timestamp>_create_articles.rb</code>) y el archivo de modelo (<code>app/models/article.rb</code>).</p><h3 id="migraciones-de-base-de-datos"><a class="anchorlink" href="#migraciones-de-base-de-datos"><span>6.2</span> Migraciones de Base de Datos</a></h3><p>Las <em>migraciones</em> se utilizan para alterar la estructura de la base de datos de una aplicación. En las aplicaciones Rails, las migraciones se escriben en Ruby para que puedan ser independientes de la base de datos.</p><p>Echemos un vistazo al contenido de nuestro nuevo archivo de migración:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">CreateArticles</span> <span class="o"><</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Migration</span><span class="p">[</span><span class="mf">7.2</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">change</span>
<span class="n">create_table</span> <span class="ss">:articles</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:title</span>
<span class="n">t</span><span class="p">.</span><span class="nf">text</span> <span class="ss">:body</span>
<span class="n">t</span><span class="p">.</span><span class="nf">timestamps</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class CreateArticles < ActiveRecord::Migration[7.2]
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
">Copy</button>
</div>
<p>La llamada a <code>create_table</code> especifica cómo debe construirse la tabla <code>articles</code>. Por defecto, el método <code>create_table</code> agrega una columna <code>id</code> como clave primaria de incremento automático. Así que el primer registro en la tabla tendrá un <code>id</code> de 1, el siguiente registro tendrá un <code>id</code> de 2, y así sucesivamente.</p><p>Dentro del bloque para <code>create_table</code>, se definen dos columnas: <code>title</code> y <code>body</code>. Estas fueron agregadas por el generador porque las incluimos en nuestro comando de generación (<code>bin/rails generate model Article title:string body:text</code>).</p><p>En la última línea del bloque hay una llamada a <code>t.timestamps</code>. Este método define dos columnas adicionales llamadas <code>created_at</code> y <code>updated_at</code>. Como veremos, Rails las gestionará por nosotros, estableciendo los valores cuando creamos o actualizamos un objeto de modelo.</p><p>Ejecutemos nuestra migración con el siguiente comando:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>db:migrate
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails db:migrate
">Copy</button>
</div>
<p>El comando mostrará una salida indicando que la tabla fue creada:</p><div class="interstitial code">
<pre><code class="highlight plaintext">== CreateArticles: migrating ===================================
-- create_table(:articles)
-> 0.0018s
== CreateArticles: migrated (0.0018s) ==========================
</code></pre>
<button class="clipboard-button" data-clipboard-text="== CreateArticles: migrating ===================================
-- create_table(:articles)
-> 0.0018s
== CreateArticles: migrated (0.0018s) ==========================
">Copy</button>
</div>
<p>CONSEJO: Para aprender más sobre migraciones, consulta <a href="active_record_migrations.html">Migraciones de Active Record</a>.</p><p>Ahora podemos interactuar con la tabla usando nuestro modelo.</p><h3 id="usando-un-modelo-para-interactuar-con-la-base-de-datos"><a class="anchorlink" href="#usando-un-modelo-para-interactuar-con-la-base-de-datos"><span>6.3</span> Usando un Modelo para Interactuar con la Base de Datos</a></h3><p>Para jugar un poco con nuestro modelo, vamos a usar una característica de Rails llamada la <em>consola</em>. La consola es un entorno de codificación interactivo al igual que <code>irb</code>, pero también carga automáticamente Rails y nuestro código de aplicación.</p><p>Iniciemos la consola con este comando:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>console
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails console
">Copy</button>
</div>
<p>Deberías ver un prompt <code>irb</code> como:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="go">Loading development environment (Rails 7.2.0)
</span><span class="gp">irb(main):001:0></span><span class="w">
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="">Copy</button>
</div>
<p>En este prompt, podemos inicializar un nuevo objeto <code>Article</code>:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="n">article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">title: </span><span class="s2">"Hello Rails"</span><span class="p">,</span> <span class="ss">body: </span><span class="s2">"I am on Rails!"</span><span class="p">)</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="article = Article.new(title: "Hello Rails", body: "I am on Rails!")
">Copy</button>
</div>
<p>Es importante notar que solo hemos <em>inicializado</em> este objeto. Este objeto no está guardado en la base de datos en absoluto. Solo está disponible en la consola en este momento. Para guardar el objeto en la base de datos, debemos llamar a <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save"><code>save</code></a>:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="n">article</span><span class="p">.</span><span class="nf">save</span>
<span class="go">(0.1ms) begin transaction
Article Create (0.4ms) INSERT INTO "articles" ("title", "body", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "Hello Rails"], ["body", "I am on Rails!"], ["created_at", "2020-01-18 23:47:30.734416"], ["updated_at", "2020-01-18 23:47:30.734416"]]
(0.9ms) commit transaction
</span><span class="p">=></span> <span class="kp">true</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="article.save
">Copy</button>
</div>
<p>La salida anterior muestra una consulta de base de datos <code>INSERT INTO "articles" ...</code>. Esto indica que el artículo ha sido insertado en nuestra tabla. Y si miramos el objeto <code>article</code> nuevamente, vemos que algo interesante ha sucedido:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="n">article</span>
<span class="gp">=> #<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30"></span><span class="w">
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="article
">Copy</button>
</div>
<p>Los atributos <code>id</code>, <code>created_at</code> y <code>updated_at</code> del objeto ahora están establecidos. Rails hizo esto por nosotros cuando guardamos el objeto.</p><p>Cuando queramos obtener este artículo de la base de datos, podemos llamar a <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find"><code>find</code></a>
en el modelo y pasar el <code>id</code> como argumento:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Article</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="gp">=> #<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30"></span><span class="w">
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="Article.find(1)
">Copy</button>
</div>
<p>Y cuando queramos obtener todos los artículos de la base de datos, podemos llamar a <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-all"><code>all</code></a>
en el modelo:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Article</span><span class="p">.</span><span class="nf">all</span>
<span class="gp">=> #<ActiveRecord::Relation [#<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30"></span><span class="p">]</span><span class="o">></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Article.all
">Copy</button>
</div>
<p>Este método devuelve un objeto <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Relation.html"><code>ActiveRecord::Relation</code></a>, que puedes pensar como un array súper-potente.</p><p>CONSEJO: Para aprender más sobre modelos, consulta <a href="active_record_basics.html">Conceptos Básicos de Active Record</a> y <a href="active_record_querying.html">Interfaz de Consulta de Active Record</a>.</p><p>Los modelos son la pieza final del rompecabezas MVC. A continuación, conectaremos todas las piezas juntas.</p><h3 id="mostrando-una-lista-de-artículos"><a class="anchorlink" href="#mostrando-una-lista-de-artículos"><span>6.4</span> Mostrando una Lista de Artículos</a></h3><p>Volvamos a nuestro controlador en <code>app/controllers/articles_controller.rb</code>, y cambiemos la acción <code>index</code> para obtener todos los artículos de la base de datos:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ArticlesController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">index</span>
<span class="vi">@articles</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">all</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ArticlesController < ApplicationController
def index
@articles = Article.all
end
end
">Copy</button>
</div>
<p>Las variables de instancia del controlador pueden ser accedidas por la vista. Eso significa que podemos referenciar <code>@articles</code> en <code>app/views/articles/index.html.erb</code>. Abramos ese archivo, y reemplacemos su contenido con:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span>Artículos<span class="nt"></h1></span>
<span class="nt"><ul></span>
<span class="cp"><%</span> <span class="vi">@articles</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">article</span><span class="o">|</span> <span class="cp">%></span>
<span class="nt"><li></span>
<span class="cp"><%=</span> <span class="n">article</span><span class="p">.</span><span class="nf">title</span> <span class="cp">%></span>
<span class="nt"></li></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="nt"></ul></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>Artículos</h1>
<ul>
<% @articles.each do |article| %>
<li>
<%= article.title %>
</li>
<% end %>
</ul>
">Copy</button>
</div>
<p>El código anterior es una mezcla de HTML y <em>ERB</em>. ERB, abreviatura de <a href="https://docs.ruby-lang.org/en/3.2/ERB.html">Ruby Embebido</a>, es un sistema de plantillas que evalúa código Ruby embebido en un documento. Aquí, podemos ver dos tipos de etiquetas ERB: <code><% %></code> y <code><%= %></code>. La etiqueta <code><% %></code> significa "evalúa el código Ruby encerrado". La etiqueta <code><%= %></code> significa "evalúa el código Ruby encerrado y muestra el valor que devuelve". Cualquier cosa que podrías escribir en un programa Ruby regular puede ir dentro de estas etiquetas ERB, aunque generalmente es mejor mantener el contenido de las etiquetas ERB corto, para la legibilidad.</p><p>Como no queremos mostrar el valor devuelto por <code>@articles.each</code>, hemos encerrado ese código en <code><% %></code>. Pero, como <em>sí</em> queremos mostrar el valor devuelto por <code>article.title</code> (para cada artículo), hemos encerrado ese código en <code><%= %></code>.</p><p>Podemos ver el resultado final visitando <a href="http://localhost:3000">http://localhost:3000</a>. (¡Recuerda que <code>bin/rails server</code> debe estar en ejecución!) Esto es lo que sucede cuando hacemos eso:</p>
<ol>
<li>El navegador hace una solicitud: <code>GET http://localhost:3000</code>.</li>
<li>Nuestra aplicación Rails recibe esta solicitud.</li>
<li>El enrutador de Rails mapea la ruta raíz a la acción <code>index</code> de <code>ArticlesController</code>.</li>
<li>La acción <code>index</code> usa el modelo <code>Article</code> para obtener todos los artículos en la base de datos.</li>
<li>Rails renderiza automáticamente la vista <code>app/views/articles/index.html.erb</code>.</li>
<li>El código ERB en la vista es evaluado para mostrar HTML.</li>
<li>El servidor envía una respuesta que contiene el HTML de vuelta al navegador.</li>
</ol>
<p>Hemos conectado todas las piezas de MVC, ¡y tenemos nuestra primera acción de controlador! A continuación, pasaremos a la segunda acción.</p><h2 id="crudit-donde-crudit-es-debido"><a class="anchorlink" href="#crudit-donde-crudit-es-debido"><span>7</span> CRUDit Donde CRUDit es Debido</a></h2><p>Casi todas las aplicaciones web involucran operaciones <a href="https://es.wikipedia.org/wiki/Crear,_leer,_actualizar_y_borrar">CRUD (Crear, Leer, Actualizar y Eliminar)</a>. Incluso puedes encontrar que la mayoría del trabajo que hace tu aplicación es CRUD. Rails reconoce esto y proporciona muchas características para ayudar a simplificar el código que hace CRUD.</p><p>Comencemos explorando estas características agregando más funcionalidad a nuestra aplicación.</p><h3 id="mostrando-un-solo-artículo"><a class="anchorlink" href="#mostrando-un-solo-artículo"><span>7.1</span> Mostrando un Solo Artículo</a></h3><p>Actualmente tenemos una vista que lista todos los artículos en nuestra base de datos. Agreguemos una nueva vista que muestre el título y el cuerpo de un solo artículo.</p><p>Comenzamos agregando una nueva ruta que mapea a una nueva acción de controlador (que agregaremos a continuación). Abre <code>config/routes.rb</code>, e inserta la última ruta mostrada aquí:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
<span class="n">root</span> <span class="s2">"articles#index"</span>
<span class="n">get</span> <span class="s2">"/articles"</span><span class="p">,</span> <span class="ss">to: </span><span class="s2">"articles#index"</span>
<span class="n">get</span> <span class="s2">"/articles/:id"</span><span class="p">,</span> <span class="ss">to: </span><span class="s2">"articles#show"</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Rails.application.routes.draw do
root "articles#index"
get "/articles", to: "articles#index"
get "/articles/:id", to: "articles#show"
end
">Copy</button>
</div>
<p>La nueva ruta es otra ruta <code>get</code>, pero tiene algo extra en su camino: <code>:id</code>. Esto designa un <em>parámetro de ruta</em>. Un parámetro de ruta captura un segmento del camino de la solicitud y pone ese valor en el Hash <code>params</code>, que es accesible por la acción del controlador. Por ejemplo, al manejar una solicitud como <code>GET http://localhost:3000/articles/1</code>, <code>1</code> sería capturado como el valor para <code>:id</code>, que luego sería accesible como <code>params[:id]</code> en la acción <code>show</code> de <code>ArticlesController</code>.</p><p>Agreguemos esa acción <code>show</code> ahora, debajo de la acción <code>index</code> en <code>app/controllers/articles_controller.rb</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ArticlesController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">index</span>
<span class="vi">@articles</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">all</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">show</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="ss">:id</span><span class="p">])</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ArticlesController < ApplicationController
def index
@articles = Article.all
end
def show
@article = Article.find(params[:id])
end
end
">Copy</button>
</div>
<p>La acción <code>show</code> llama a <code>Article.find</code> (mencionado anteriormente) con el ID capturado por el parámetro de ruta. El artículo devuelto se almacena en la variable de instancia <code>@article</code>, por lo que es accesible por la vista. Por defecto, la acción <code>show</code> renderizará <code>app/views/articles/show.html.erb</code>.</p><p>Vamos a crear <code>app/views/articles/show.html.erb</code>, con el siguiente contenido:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span><span class="cp"><%=</span> <span class="vi">@article</span><span class="p">.</span><span class="nf">title</span> <span class="cp">%></span><span class="nt"></h1></span>
<span class="nt"><p></span><span class="cp"><%=</span> <span class="vi">@article</span><span class="p">.</span><span class="nf">body</span> <span class="cp">%></span><span class="nt"></p></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1><%= @article.title %></h1>
<p><%= @article.body %></p>
">Copy</button>
</div>
<p>¡Ahora podemos ver el artículo cuando visitamos <a href="http://localhost:3000/articles/1">http://localhost:3000/articles/1</a>!</p><p>Para terminar, agreguemos una forma conveniente de llegar a la página de un artículo. Enlazaremos el título de cada artículo en <code>app/views/articles/index.html.erb</code> a su página:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span>Artículos<span class="nt"></h1></span>
<span class="nt"><ul></span>
<span class="cp"><%</span> <span class="vi">@articles</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">article</span><span class="o">|</span> <span class="cp">%></span>
<span class="nt"><li></span>
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"/articles/</span><span class="cp"><%=</span> <span class="n">article</span><span class="p">.</span><span class="nf">id</span> <span class="cp">%></span><span class="s">"</span><span class="nt">></span>
<span class="cp"><%=</span> <span class="n">article</span><span class="p">.</span><span class="nf">title</span> <span class="cp">%></span>
<span class="nt"></a></span>
<span class="nt"></li></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="nt"></ul></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>Artículos</h1>
<ul>
<% @articles.each do |article| %>
<li>
<a href="/articles/<%= article.id %>">
<%= article.title %>
</a>
</li>
<% end %>
</ul>
">Copy</button>
</div>
<h3 id="enrutamiento-de-recursos"><a class="anchorlink" href="#enrutamiento-de-recursos"><span>7.2</span> Enrutamiento de Recursos</a></h3><p>Hasta ahora, hemos cubierto la "R" (Leer) de CRUD. Eventualmente cubriremos la "C" (Crear), "U" (Actualizar) y "D" (Eliminar). Como habrás adivinado, lo haremos agregando nuevas rutas, acciones de controlador y vistas. Siempre que tengamos una combinación de rutas, acciones de controlador y vistas que trabajen juntas para realizar operaciones CRUD en una entidad, llamamos a esa entidad un <em>recurso</em>. Por ejemplo, en nuestra aplicación, diríamos que un artículo es un recurso.</p><p>Rails proporciona un método de rutas llamado <a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-resources"><code>resources</code></a>
que mapea todas las rutas convencionales para una colección de recursos, como artículos. Así que antes de proceder a las secciones "C", "U" y "D", reemplacemos las dos rutas <code>get</code> en <code>config/routes.rb</code> con <code>resources</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
<span class="n">root</span> <span class="s2">"articles#index"</span>
<span class="n">resources</span> <span class="ss">:articles</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Rails.application.routes.draw do
root "articles#index"
resources :articles
end
">Copy</button>
</div>
<p>Podemos inspeccionar qué rutas están mapeadas ejecutando el comando <code>bin/rails routes</code>:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>routes
<span class="gp"> Prefix Verb URI Pattern Controller#</span>Action
<span class="gp"> root GET / articles#</span>index
<span class="gp"> articles GET /articles(.:format) articles#</span>index
<span class="gp"> new_article GET /articles/new(.:format) articles#</span>new
<span class="gp"> article GET /articles/:id(.:format) articles#</span>show
<span class="gp"> POST /articles(.:format) articles#</span>create
<span class="gp">edit_article GET /articles/:id/edit(.:format) articles#</span>edit
<span class="gp"> PATCH /articles/:id(.:format) articles#</span>update
<span class="gp"> DELETE /articles/:id(.:format) articles#</span>destroy
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails routes
">Copy</button>
</div>
<p>El método <code>resources</code> también configura métodos de ayuda de URL y ruta que podemos usar para evitar que nuestro código dependa de una configuración de ruta específica. Los valores en la columna "Prefix" arriba más un sufijo de <code>_url</code> o <code>_path</code> forman los nombres de estos ayudantes. Por ejemplo, el ayudante <code>article_path</code> devuelve <code>"/articles/#{article.id}"</code> cuando se le da un artículo. Podemos usarlo para ordenar nuestros enlaces en <code>app/views/articles/index.html.erb</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span>Artículos<span class="nt"></h1></span>
<span class="nt"><ul></span>
<span class="cp"><%</span> <span class="vi">@articles</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">article</span><span class="o">|</span> <span class="cp">%></span>
<span class="nt"><li></span>
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"</span><span class="cp"><%=</span> <span class="n">article_path</span><span class="p">(</span><span class="n">article</span><span class="p">)</span> <span class="cp">%></span><span class="s">"</span><span class="nt">></span>
<span class="cp"><%=</span> <span class="n">article</span><span class="p">.</span><span class="nf">title</span> <span class="cp">%></span>
<span class="nt"></a></span>
<span class="nt"></li></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="nt"></ul></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>Artículos</h1>
<ul>
<% @articles.each do |article| %>
<li>
<a href="<%= article_path(article) %>">
<%= article.title %>
</a>
</li>
<% end %>
</ul>
">Copy</button>
</div>
<p>Sin embargo, llevaremos esto un paso más allá utilizando el ayudante <a href="https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to"><code>link_to</code></a>.
El ayudante <code>link_to</code> renderiza un enlace con su primer argumento como el texto del enlace y su segundo argumento como el destino del enlace. Si pasamos un objeto de modelo como el segundo argumento, <code>link_to</code> llamará al ayudante de camino apropiado para convertir el objeto en un camino. Por ejemplo, si pasamos un artículo, <code>link_to</code> llamará a <code>article_path</code>. Así que <code>app/views/articles/index.html.erb</code> se convierte en:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span>Artículos<span class="nt"></h1></span>
<span class="nt"><ul></span>
<span class="cp"><%</span> <span class="vi">@articles</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">article</span><span class="o">|</span> <span class="cp">%></span>
<span class="nt"><li></span>
<span class="cp"><%=</span> <span class="n">link_to</span> <span class="n">article</span><span class="p">.</span><span class="nf">title</span><span class="p">,</span> <span class="n">article</span> <span class="cp">%></span>
<span class="nt"></li></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="nt"></ul></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>Artículos</h1>
<ul>
<% @articles.each do |article| %>
<li>
<%= link_to article.title, article %>
</li>
<% end %>
</ul>
">Copy</button>
</div>
<p>¡Genial!</p><p>CONSEJO: Para aprender más sobre enrutamiento, consulta <a href="routing.html">Enrutamiento de Rails desde el Exterior hacia Adentro</a>.</p><h3 id="creando-un-nuevo-artículo"><a class="anchorlink" href="#creando-un-nuevo-artículo"><span>7.3</span> Creando un Nuevo Artículo</a></h3><p>Ahora pasamos a la "C" (Crear) de CRUD. Típicamente, en aplicaciones web, crear un nuevo recurso es un proceso de varios pasos. Primero, el usuario solicita un formulario para completar. Luego, el usuario envía el formulario. Si no hay errores, entonces el recurso se crea y se muestra algún tipo de confirmación. De lo contrario, el formulario se muestra nuevamente con mensajes de error, y el proceso se repite.</p><p>En una aplicación Rails, estos pasos son manejados convencionalmente por las acciones <code>new</code> y <code>create</code> de un controlador. Agreguemos una implementación típica de estas acciones a <code>app/controllers/articles_controller.rb</code>, debajo de la acción <code>show</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ArticlesController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">index</span>
<span class="vi">@articles</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">all</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">show</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="ss">:id</span><span class="p">])</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">new</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">create</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">title: </span><span class="s2">"..."</span><span class="p">,</span> <span class="ss">body: </span><span class="s2">"..."</span><span class="p">)</span>
<span class="k">if</span> <span class="vi">@article</span><span class="p">.</span><span class="nf">save</span>
<span class="n">redirect_to</span> <span class="vi">@article</span>
<span class="k">else</span>
<span class="n">render</span> <span class="ss">:new</span><span class="p">,</span> <span class="ss">status: :unprocessable_entity</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ArticlesController < ApplicationController
def index
@articles = Article.all
end
def show
@article = Article.find(params[:id])
end
def new
@article = Article.new
end
def create
@article = Article.new(title: "...", body: "...")
if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end
end
">Copy</button>
</div>
<p>La acción <code>new</code> instancia un nuevo artículo, pero no lo guarda. Este artículo se usará en la vista al construir el formulario. Por defecto, la acción <code>new</code> renderizará <code>app/views/articles/new.html.erb</code>, que crearemos a continuación.</p><p>La acción <code>create</code> instancia un nuevo artículo con valores para el título y el cuerpo, e intenta guardarlo. Si el artículo se guarda con éxito, la acción redirige el navegador a la página del artículo en <code>"http://localhost:3000/articles/#{@article.id}"</code>. De lo contrario, la acción muestra nuevamente el formulario renderizando <code>app/views/articles/new.html.erb</code> con el código de estado <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422">422 Entidad No Procesable</a>. El título y el cuerpo aquí son valores ficticios. Después de crear el formulario, volveremos y cambiaremos estos.</p><p>NOTA: <a href="https://edgeapi.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to"><code>redirect_to</code></a>
hará que el navegador haga una nueva solicitud,
mientras que <a href="https://edgeapi.rubyonrails.org/classes/AbstractController/Rendering.html#method-i-render"><code>render</code></a>
renderiza la vista especificada para la solicitud actual.
Es importante usar <code>redirect_to</code> después de mutar la base de datos o el estado de la aplicación.
De lo contrario, si el usuario actualiza la página, el navegador hará la misma solicitud, y la mutación se repetirá.</p><h4 id="usando-un-constructor-de-formularios"><a class="anchorlink" href="#usando-un-constructor-de-formularios"><span>7.3.1</span> Usando un Constructor de Formularios</a></h4><p>Usaremos una característica de Rails llamada un <em>constructor de formularios</em> para crear nuestro formulario. Usando un constructor de formularios, podemos escribir una cantidad mínima de código para mostrar un formulario que esté completamente configurado y siga las convenciones de Rails.</p><p>Creemos <code>app/views/articles/new.html.erb</code> con el siguiente contenido:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span>Nuevo Artículo<span class="nt"></h1></span>
<span class="cp"><%=</span> <span class="n">form_with</span> <span class="ss">model: </span><span class="vi">@article</span> <span class="k">do</span> <span class="o">|</span><span class="n">form</span><span class="o">|</span> <span class="cp">%></span>
<span class="nt"><div></span>
<span class="cp"><%=</span> <span class="n">form</span><span class="p">.</span><span class="nf">label</span> <span class="ss">:title</span> <span class="cp">%></span><span class="nt"><br></span>
<span class="cp"><%=</span> <span class="n">form</span><span class="p">.</span><span class="nf">text_field</span> <span class="ss">:title</span> <span class="cp">%></span>
<span class="nt"></div></span>
<span class="nt"><div></span>
<span class="cp"><%=</span> <span class="n">form</span><span class="p">.</span><span class="nf">label</span> <span class="ss">:body</span> <span class="cp">%></span><span class="nt"><br></span>
<span class="cp"><%=</span> <span class="n">form</span><span class="p">.</span><span class="nf">text_area</span> <span class="ss">:body</span> <span class="cp">%></span>
<span class="nt"></div></span>
<span class="nt"><div></span>
<span class="cp"><%=</span> <span class="n">form</span><span class="p">.</span><span class="nf">submit</span> <span class="cp">%></span>
<span class="nt"></div></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>Nuevo Artículo</h1>
<%= form_with model: @article do |form| %>
<div>
<%= form.label :title %><br>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :body %><br>
<%= form.text_area :body %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
">Copy</button>
</div>
<p>El método de ayuda <a href="https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with"><code>form_with</code></a>
instancia un constructor de formularios. En el bloque <code>form_with</code> llamamos a
métodos como <a href="https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-label"><code>label</code></a>
y <a href="https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-text_field"><code>text_field</code></a>
en el constructor de formularios para mostrar los elementos de formulario apropiados.</p><p>La salida resultante de nuestra llamada a <code>form_with</code> se verá como:</p><div class="interstitial code">
<pre><code class="highlight html"><span class="nt"><form</span> <span class="na">action=</span><span class="s">"/articles"</span> <span class="na">accept-charset=</span><span class="s">"UTF-8"</span> <span class="na">method=</span><span class="s">"post"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"hidden"</span> <span class="na">name=</span><span class="s">"authenticity_token"</span> <span class="na">value=</span><span class="s">"..."</span><span class="nt">></span>
<span class="nt"><div></span>
<span class="nt"><label</span> <span class="na">for=</span><span class="s">"article_title"</span><span class="nt">></span>Title<span class="nt"></label><br></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"article[title]"</span> <span class="na">id=</span><span class="s">"article_title"</span><span class="nt">></span>
<span class="nt"></div></span>
<span class="nt"><div></span>
<span class="nt"><label</span> <span class="na">for=</span><span class="s">"article_body"</span><span class="nt">></span>Body<span class="nt"></label><br></span>
<span class="nt"><textarea</span> <span class="na">name=</span><span class="s">"article[body]"</span> <span class="na">id=</span><span class="s">"article_body"</span><span class="nt">></textarea></span>
<span class="nt"></div></span>
<span class="nt"><div></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">name=</span><span class="s">"commit"</span> <span class="na">value=</span><span class="s">"Create Article"</span> <span class="na">data-disable-with=</span><span class="s">"Create Article"</span><span class="nt">></span>
<span class="nt"></div></span>
<span class="nt"></form></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<form action="/articles" accept-charset="UTF-8" method="post">
<input type="hidden" name="authenticity_token" value="...">
<div>
<label for="article_title">Title</label><br>
<input type="text" name="article[title]" id="article_title">
</div>
<div>
<label for="article_body">Body</label><br>
<textarea name="article[body]" id="article_body"></textarea>
</div>
<div>
<input type="submit" name="commit" value="Create Article" data-disable-with="Create Article">
</div>
</form>
">Copy</button>
</div>
<p>CONSEJO: Para aprender más sobre constructores de formularios, consulta <a href="form_helpers.html">Ayudantes de Formularios de Vista de Acción</a>.</p><h4 id="usando-parámetros-fuertes"><a class="anchorlink" href="#usando-parámetros-fuertes"><span>7.3.2</span> Usando Parámetros Fuertes</a></h4><p>Los datos enviados del formulario se colocan en el Hash <code>params</code>, junto con los parámetros de ruta capturados. Por lo tanto, la acción <code>create</code> puede acceder al título enviado a través de <code>params[:article][:title]</code> y al cuerpo enviado a través de <code>params[:article][:body]</code>. Podríamos pasar estos valores individualmente a <code>Article.new</code>, pero eso sería verboso y posiblemente propenso a errores. Y se volvería peor a medida que agreguemos más campos.</p><p>En su lugar, pasaremos un solo Hash que contenga los valores. Sin embargo, aún debemos especificar qué valores están permitidos en ese Hash. De lo contrario, un usuario malintencionado podría potencialmente enviar campos de formulario adicionales y sobrescribir datos privados. De hecho, si pasamos el Hash <code>params[:article]</code> sin filtrar directamente a <code>Article.new</code>, Rails arrojará un <code>ForbiddenAttributesError</code> para alertarnos sobre el problema. Así que usaremos una característica de Rails llamada <em>Parámetros Fuertes</em> para filtrar <code>params</code>. Piénsalo como <a href="https://es.wikipedia.org/wiki/Tipado_fuerte_y_d%C3%A9bil">tipado fuerte</a>
para <code>params</code>.</p><p>Agreguemos un método privado al final de <code>app/controllers/articles_controller.rb</code>
llamado <code>article_params</code> que filtre <code>params</code>. Y cambiemos <code>create</code> para usarlo:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ArticlesController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">index</span>
<span class="vi">@articles</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">all</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">show</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="n">params</span><span class="p">[</span><span class="ss">:id</span><span class="p">])</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">new</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">create</span>
<span class="vi">@article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">article_params</span><span class="p">)</span>
<span class="k">if</span> <span class="vi">@article</span><span class="p">.</span><span class="nf">save</span>
<span class="n">redirect_to</span> <span class="vi">@article</span>
<span class="k">else</span>
<span class="n">render</span> <span class="ss">:new</span><span class="p">,</span> <span class="ss">status: :unprocessable_entity</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nf">article_params</span>
<span class="n">params</span><span class="p">.</span><span class="nf">require</span><span class="p">(</span><span class="ss">:article</span><span class="p">).</span><span class="nf">permit</span><span class="p">(</span><span class="ss">:title</span><span class="p">,</span> <span class="ss">:body</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ArticlesController < ApplicationController
def index
@articles = Article.all
end
def show
@article = Article.find(params[:id])
end
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end