-
Notifications
You must be signed in to change notification settings - Fork 0
/
action_view_overview.html
1070 lines (1007 loc) · 82.5 KB
/
action_view_overview.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>Descripción General de Action View — 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="Descripción General de Action View — 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.Descripción General de Action ViewDespués de leer esta guía, sabrás: Qué es Action View y cómo usarlo con Rails. Cómo usar mejor las plantillas, parciales y diseños. Cómo usar vistas localizadas." />
<meta property="og:description" content="NO LEA ESTE ARCHIVO EN GITHUB, LAS GUÍAS ESTÁN PUBLICADAS EN https://guides.rubyonrails.org.Descripción General de Action ViewDespués de leer esta guía, sabrás: Qué es Action View y cómo usarlo con Rails. Cómo usar mejor las plantillas, parciales y diseños. Cómo usar vistas localizadas." />
<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>Descripción General de Action View</h1><p>Después de leer esta guía, sabrás:</p>
<ul>
<li>Qué es Action View y cómo usarlo con Rails.</li>
<li>Cómo usar mejor las plantillas, parciales y diseños.</li>
<li>Cómo usar vistas localizadas.</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="#¿qué-es-action-view-questionmark">¿Qué es Action View?</a></li>
<li><a href="#usando-action-view-con-rails">Usando Action View con Rails</a></li>
<li><a href="#plantillas">Plantillas</a>
<ul>
<li><a href="#erb">ERB</a></li>
<li><a href="#jbuilder">Jbuilder</a></li>
<li><a href="#builder">Builder</a></li>
<li><a href="#compilación-de-plantillas">Compilación de Plantillas</a></li>
</ul></li>
<li><a href="#parciales">Parciales</a>
<ul>
<li><a href="#renderizando-parciales">Renderizando Parciales</a></li>
<li><a href="#usando-parciales-para-simplificar-vistas">Usando Parciales para Simplificar Vistas</a></li>
<li><a href="#pasando-datos-a-parciales-con-la-opción-locals">Pasando Datos a Parciales con la Opción <code>locals</code></a></li>
<li><a href="#usando-local-assigns">Usando <code>local_assigns</code></a></li>
<li><a href="#render-sin-opciones-partial-y-locals"><code>render</code> sin Opciones <code>partial</code> y <code>locals</code></a></li>
<li><a href="#las-opciones-as-y-object">Las Opciones <code>as</code> y <code>object</code></a></li>
<li><a href="#renderizando-colecciones">Renderizando Colecciones</a></li>
<li><a href="#plantillas-de-espaciador">Plantillas de Espaciador</a></li>
<li><a href="#variables-de-contador">Variables de Contador</a></li>
<li><a href="#local-assigns-con-coincidencia-de-patrones"><code>local_assigns</code> con Coincidencia de Patrones</a></li>
<li><a href="#locales-estrictos">Locales Estrictos</a></li>
</ul></li>
<li><a href="#diseños">Diseños</a>
<ul>
<li><a href="#diseños-parciales">Diseños Parciales</a></li>
<li><a href="#colección-con-diseños-parciales">Colección con Diseños Parciales</a></li>
</ul></li>
<li><a href="#helpers">Helpers</a></li>
<li><a href="#vistas-localizadas">Vistas Localizadas</a></li>
</ol>
</nav>
<hr>
</div>
</section>
<main id="container">
<div class="wrapper">
<div id="mainCol">
<h2 id="¿qué-es-action-view-questionmark"><a class="anchorlink" href="#¿qué-es-action-view-questionmark"><span>1</span> ¿Qué es Action View?</a></h2><p>Action View es la V en
<a href="https://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador">MVC</a>.
<a href="action_controller_overview.html">Action Controller</a> y Action View trabajan
juntos para manejar solicitudes web. Action Controller se encarga de
comunicarse con la capa del modelo (de MVC) y recuperar datos. Action View es
entonces responsable de renderizar un cuerpo de respuesta a la solicitud web usando esos
datos.</p><p>Por defecto, las plantillas de Action View (también referidas simplemente como "vistas") están
escritas usando Ruby Embebido (ERB), lo que permite usar código Ruby dentro de
documentos HTML.</p><p>Action View proporciona muchos métodos <a href="#helpers">helper</a> para generar
dinámicamente etiquetas HTML para formularios, fechas y cadenas. También es
posible agregar helpers personalizados a tu aplicación según sea necesario.</p><p>NOTA: Action View puede hacer uso de características de Active Model como
<a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Conversion.html#method-i-to_param"><code>to_param</code></a>
y
<a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Conversion.html#method-i-to_partial_path"><code>to_partial_path</code></a>
para simplificar el código. Eso no significa que Action View dependa de Active Model. Action
View es un paquete independiente que se puede usar con cualquier biblioteca Ruby.</p><h2 id="usando-action-view-con-rails"><a class="anchorlink" href="#usando-action-view-con-rails"><span>2</span> Usando Action View con Rails</a></h2><p>Las plantillas de Action View (también conocidas como "vistas") se almacenan en subdirectorios en el
directorio <code>app/views</code>. Hay un subdirectorio que coincide con el nombre de cada
controlador. Los archivos de vista dentro de ese subdirectorio se utilizan para renderizar vistas específicas
como respuesta a acciones del controlador.</p><p>Por ejemplo, cuando usas scaffolding para generar un recurso <code>article</code>, Rails
genera los siguientes archivos en <code>app/views/articles</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>generate scaffold article
<span class="go"> [...]
invoke scaffold_controller
create app/controllers/articles_controller.rb
invoke erb
create app/views/articles
create app/views/articles/index.html.erb
create app/views/articles/edit.html.erb
create app/views/articles/show.html.erb
create app/views/articles/new.html.erb
create app/views/articles/_form.html.erb
[...]
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails generate scaffold article
">Copy</button>
</div>
<p>Los nombres de los archivos siguen una convención de nomenclatura de Rails. Comparten su nombre con la
acción del controlador asociada. Por ejemplo, <code>index.html.erb</code>, <code>edit.html.erb</code>,
etc.</p><p>Al seguir esta convención de nomenclatura, Rails encontrará automáticamente y renderizará
la vista correspondiente al final de una acción del controlador, sin que tengas que
especificarlo. Por ejemplo, la acción <code>index</code> en el <code>articles_controller.rb</code> renderizará
automáticamente la vista <code>index.html.erb</code> dentro del directorio <code>app/views/articles/</code>.
El nombre y la ubicación del archivo son importantes.</p><p>El HTML final devuelto al cliente se compone de una combinación del
archivo ERB <code>.html.erb</code>, una plantilla de diseño que lo envuelve, y todos los parciales que
el archivo ERB pueda referenciar. En el resto de esta guía, encontrarás más
detalles sobre cada uno de los tres componentes: <code>Plantillas</code>, <code>Parciales</code>, <code>Diseños</code>.</p><h2 id="plantillas"><a class="anchorlink" href="#plantillas"><span>3</span> Plantillas</a></h2><p>Las plantillas de Action View pueden escribirse en diferentes formatos. Si el archivo de plantilla
tiene una extensión <code>.erb</code>, utiliza Ruby embebido para construir una respuesta HTML. Si la
plantilla tiene una extensión <code>.jbuilder</code>, utiliza la gema
<a href="https://github.com/rails/jbuilder">Jbuilder</a> para construir una respuesta JSON. Y
una plantilla con una extensión <code>.builder</code> utiliza la
librería <a href="https://github.com/rails/builder"><code>Builder::XmlMarkup</code></a> para construir una respuesta XML.</p><p>Rails usa la extensión del archivo para distinguir entre múltiples sistemas de plantillas.
Por ejemplo, un archivo HTML que usa el sistema de plantillas ERB tendrá <code>.html.erb</code> como
extensión de archivo, y un archivo JSON que usa el sistema de plantillas Jbuilder tendrá
la extensión de archivo <code>.json.jbuilder</code>. Otras bibliotecas pueden agregar otros tipos de plantillas
y extensiones de archivo también.</p><h3 id="erb"><a class="anchorlink" href="#erb"><span>3.1</span> ERB</a></h3><p>Una plantilla ERB es una manera de esparcir código Ruby dentro de HTML estático
usando etiquetas ERB especiales como <code><% %></code> y <code><%= %></code>.</p><p>Cuando Rails procesa las plantillas de vista ERB que terminan con <code>.html.erb</code>, evalúa
el código Ruby embebido y reemplaza las etiquetas ERB con la salida dinámica.
Ese contenido dinámico se combina con el marcado HTML estático para formar la
respuesta HTML final.</p><p>Dentro de una plantilla ERB, se puede incluir código Ruby usando tanto las etiquetas <code><% %></code> como
<code><%= %></code>. La etiqueta <code><% %></code> (sin el <code>=</code>) se usa cuando quieres ejecutar
código Ruby pero no directamente mostrar el resultado, como condiciones o bucles. La
etiqueta <code><%= %></code> se usa para código Ruby que genera una salida y quieres que
esa salida se renderice dentro de la plantilla, como un atributo de modelo como
<code>person.name</code> en este ejemplo:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="nt"><h1></span>Nombres<span class="nt"></h1></span>
<span class="cp"><%</span> <span class="vi">@people</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">person</span><span class="o">|</span> <span class="cp">%></span>
Nombre: <span class="cp"><%=</span> <span class="n">person</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%></span><span class="nt"><br></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<h1>Nombres</h1>
<% @people.each do |person| %>
Nombre: <%= person.name %><br>
<% end %>
">Copy</button>
</div>
<p>El bucle se configura usando etiquetas de incrustación regulares (<code><% %></code>) y el nombre se
inserta usando las etiquetas de incrustación de salida (<code><%= %></code>).</p><p>Ten en cuenta que funciones como <code>print</code> y <code>puts</code> no se renderizarán en la vista
con plantillas ERB. Así que algo como esto no funcionaría:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# INCORRECTO %></span>
Hola, Sr. <span class="cp"><%</span> <span class="nb">puts</span> <span class="s2">"Frodo"</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%# INCORRECTO %>
Hola, Sr. <% puts "Frodo" %>
">Copy</button>
</div>
<p>El ejemplo anterior muestra que se pueden agregar comentarios en ERB dentro de la etiqueta <code><%# %></code>.</p><p>Para suprimir espacios en blanco iniciales y finales, puedes usar <code><%-</code> <code>-%></code>
intercambiablemente con <code><%</code> y <code>%></code>.</p><h3 id="jbuilder"><a class="anchorlink" href="#jbuilder"><span>3.2</span> Jbuilder</a></h3><p><code>Jbuilder</code> es una gema mantenida por el equipo de Rails e incluida en el
<code>Gemfile</code> por defecto de Rails. Se utiliza para construir respuestas JSON usando plantillas.</p><p>Si no lo tienes, puedes agregar lo siguiente a tu <code>Gemfile</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">gem</span> <span class="s2">"jbuilder"</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="gem "jbuilder"
">Copy</button>
</div>
<p>Un objeto <code>Jbuilder</code> llamado <code>json</code> está disponible automáticamente para las plantillas
con una extensión <code>.jbuilder</code>.</p><p>Aquí hay un ejemplo básico:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">json</span><span class="p">.</span><span class="nf">name</span><span class="p">(</span><span class="s2">"Alex"</span><span class="p">)</span>
<span class="n">json</span><span class="p">.</span><span class="nf">email</span><span class="p">(</span><span class="s2">"[email protected]"</span><span class="p">)</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="json.name("Alex")
json.email("[email protected]")
">Copy</button>
</div>
<p>produciría:</p><div class="interstitial code">
<pre><code class="highlight json"><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Alex"</span><span class="p">,</span><span class="w">
</span><span class="nl">"email"</span><span class="p">:</span><span class="w"> </span><span class="s2">"[email protected]"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="{
"name": "Alex",
"email": "[email protected]"
}
">Copy</button>
</div>
<p>Consulta la <a href="https://github.com/rails/jbuilder#jbuilder">documentación de Jbuilder</a> para
más ejemplos.</p><h3 id="builder"><a class="anchorlink" href="#builder"><span>3.3</span> Builder</a></h3><p>Las plantillas Builder son una alternativa más programática a ERB. Es similar a
<code>JBuilder</code> pero se utiliza para generar XML, en lugar de JSON.</p><p>Un objeto <code>XmlMarkup</code> llamado <code>xml</code> está disponible automáticamente para las plantillas
con una extensión <code>.builder</code>.</p><p>Aquí hay un ejemplo básico:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">xml</span><span class="p">.</span><span class="nf">em</span><span class="p">(</span><span class="s2">"enfatizado"</span><span class="p">)</span>
<span class="n">xml</span><span class="p">.</span><span class="nf">em</span> <span class="p">{</span> <span class="n">xml</span><span class="p">.</span><span class="nf">b</span><span class="p">(</span><span class="s2">"énfasis y negrita"</span><span class="p">)</span> <span class="p">}</span>
<span class="n">xml</span><span class="p">.</span><span class="nf">a</span><span class="p">(</span><span class="s2">"Un Enlace"</span><span class="p">,</span> <span class="s2">"href"</span> <span class="o">=></span> <span class="s2">"https://rubyonrails.org"</span><span class="p">)</span>
<span class="n">xml</span><span class="p">.</span><span class="nf">target</span><span class="p">(</span><span class="s2">"name"</span> <span class="o">=></span> <span class="s2">"compilar"</span><span class="p">,</span> <span class="s2">"option"</span> <span class="o">=></span> <span class="s2">"rápido"</span><span class="p">)</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="xml.em("enfatizado")
xml.em { xml.b("énfasis y negrita") }
xml.a("Un Enlace", "href" => "https://rubyonrails.org")
xml.target("name" => "compilar", "option" => "rápido")
">Copy</button>
</div>
<p>lo cual produciría:</p><div class="interstitial code">
<pre><code class="highlight html"><span class="nt"><em></span>enfatizado<span class="nt"></em></span>
<span class="nt"><em><b></span>énfasis <span class="ni">&amp;</span> negrita<span class="nt"></b></em></span>
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"https://rubyonrails.org"</span><span class="nt">></span>Un enlace<span class="nt"></a></span>
<span class="nt"><target</span> <span class="na">option=</span><span class="s">"rápido"</span> <span class="na">name=</span><span class="s">"compilar"</span> <span class="nt">/></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<em>enfatizado</em>
<em><b>énfasis &amp; negrita</b></em>
<a href="https://rubyonrails.org">Un enlace</a>
<target option="rápido" name="compilar" />
">Copy</button>
</div>
<p>Cualquier método con un bloque se tratará como una etiqueta de marcado XML con
marcado anidado en el bloque. Por ejemplo, lo siguiente:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">xml</span><span class="p">.</span><span class="nf">div</span> <span class="p">{</span>
<span class="n">xml</span><span class="p">.</span><span class="nf">h1</span><span class="p">(</span><span class="vi">@person</span><span class="p">.</span><span class="nf">name</span><span class="p">)</span>
<span class="n">xml</span><span class="p">.</span><span class="nf">p</span><span class="p">(</span><span class="vi">@person</span><span class="p">.</span><span class="nf">bio</span><span class="p">)</span>
<span class="p">}</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="xml.div {
xml.h1(@person.name)
xml.p(@person.bio)
}
">Copy</button>
</div>
<p>produciría algo como:</p><div class="interstitial code">
<pre><code class="highlight html"><span class="nt"><div></span>
<span class="nt"><h1></span>David Heinemeier Hansson<span class="nt"></h1></span>
<span class="nt"><p></span>Un producto del Diseño Danés durante el Invierno del '79...<span class="nt"></p></span>
<span class="nt"></div></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<div>
<h1>David Heinemeier Hansson</h1>
<p>Un producto del Diseño Danés durante el Invierno del '79...</p>
</div>
">Copy</button>
</div>
<p>Consulta la <a href="https://github.com/rails/builder">documentación de Builder</a> para más ejemplos.</p><h3 id="compilación-de-plantillas"><a class="anchorlink" href="#compilación-de-plantillas"><span>3.4</span> Compilación de Plantillas</a></h3><p>Por defecto, Rails compilará cada plantilla en un método para renderizarla. En el
entorno de desarrollo, cuando alteras una plantilla, Rails verificará el tiempo
de modificación del archivo y lo recompilará.</p><p>También hay almacenamiento en caché de fragmentos para cuando diferentes partes de la
página necesitan ser almacenadas y caducadas por separado. Aprende más sobre esto en la <a href="caching_with_rails.html#fragment-caching">guía de
almacenamiento en caché</a>.</p><h2 id="parciales"><a class="anchorlink" href="#parciales"><span>4</span> Parciales</a></h2><p>Las plantillas parciales, usualmente llamadas simplemente "parciales", son una manera de dividir
las plantillas de vista en fragmentos más pequeños y reutilizables. Con parciales, puedes extraer
un fragmento de código de tu plantilla principal a un archivo separado más pequeño, y renderizar
ese archivo en la plantilla principal. También puedes pasar datos a los archivos parciales desde
la plantilla principal.</p><p>Veamos esto en acción con algunos ejemplos:</p><h3 id="renderizando-parciales"><a class="anchorlink" href="#renderizando-parciales"><span>4.1</span> Renderizando Parciales</a></h3><p>Para renderizar un parcial como parte de una vista, usas el
método <a href="https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/RenderingHelper.html#method-i-render"><code>render</code></a>
dentro de la vista:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="s2">"product"</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render "product" %>
">Copy</button>
</div>
<p>Esto buscará un archivo llamado <code>_product.html.erb</code> en la misma carpeta para
renderizar dentro de esa vista. Los nombres de archivo parciales comienzan con un carácter de guion bajo
por convención. El nombre del archivo distingue los parciales de las vistas regulares. Sin embargo, no
se usa guion bajo al referirse a parciales para renderizar dentro de una vista. Esto es
cierto incluso cuando refieres un parcial de otro directorio:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="s2">"application/product"</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render "application/product" %>
">Copy</button>
</div>
<p>Ese código buscará y mostrará un archivo parcial llamado <code>_product.html.erb</code> en
<code>app/views/application/</code>.</p><h3 id="usando-parciales-para-simplificar-vistas"><a class="anchorlink" href="#usando-parciales-para-simplificar-vistas"><span>4.2</span> Usando Parciales para Simplificar Vistas</a></h3><p>Una manera de usar parciales es tratarlos como el equivalente de métodos. Una forma de
mover detalles fuera de una vista para que puedas entender más fácilmente lo que está pasando.
Por ejemplo, podrías tener una vista que se vea así:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="s2">"application/ad_banner"</span> <span class="cp">%></span>
<span class="nt"><h1></span>Productos<span class="nt"></h1></span>
<span class="nt"><p></span>Aquí hay algunos de nuestros excelentes productos:<span class="nt"></p></span>
<span class="cp"><%</span> <span class="vi">@products</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">product</span><span class="o">|</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">product: </span><span class="n">product</span> <span class="p">}</span> <span class="cp">%></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="s2">"application/footer"</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render "application/ad_banner" %>
<h1>Productos</h1>
<p>Aquí hay algunos de nuestros excelentes productos:</p>
<% @products.each do |product| %>
<%= render partial: "product", locals: { product: product } %>
<% end %>
<%= render "application/footer" %>
">Copy</button>
</div>
<p>Aquí, los parciales <code>_ad_banner.html.erb</code> y <code>_footer.html.erb</code> podrían contener
contenido que se comparte entre muchas páginas en tu aplicación. No necesitas
ver los detalles de estas secciones cuando estás enfocado en una página de Productos.</p><p>El ejemplo anterior también usa el parcial <code>_product.html.erb</code>. Este parcial
contiene detalles para renderizar un producto individual y se usa para renderizar cada
producto en la colección <code>@products</code>.</p><h3 id="pasando-datos-a-parciales-con-la-opción-locals"><a class="anchorlink" href="#pasando-datos-a-parciales-con-la-opción-locals"><span>4.3</span> Pasando Datos a Parciales con la Opción <code>locals</code></a></h3><p>Al renderizar un parcial, puedes pasar datos al parcial desde la vista que lo
renderiza. Usas la opción <code>locals:</code> hash para esto. Cada clave en la opción
<code>locals:</code> está disponible como una variable local del parcial:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/products/show.html.erb %></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">my_product: </span><span class="vi">@product</span> <span class="p">}</span> <span class="cp">%></span>
<span class="c"><%# app/views/products/_product.html.erb %></span>
<span class="cp"><%=</span> <span class="n">tag</span><span class="p">.</span><span class="nf">div</span> <span class="ss">id: </span><span class="n">dom_id</span><span class="p">(</span><span class="n">my_product</span><span class="p">)</span> <span class="k">do</span> <span class="cp">%></span>
<span class="nt"><h1></span><span class="cp"><%=</span> <span class="n">my_product</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%></span><span class="nt"></h1></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%= render partial: "product", locals: { my_product: @product } %>
<%= tag.div id: dom_id(my_product) do %>
<h1><%= my_product.name %></h1>
<% end %>
">Copy</button>
</div>
<p>Una "variable local de parcial" es una variable que es local a un parcial dado y
solo está disponible dentro de ese parcial. En el ejemplo anterior, <code>my_product</code> es una
variable local de parcial. Se le asignó el valor de <code>@product</code> cuando se pasó al
parcial desde la vista original.</p><p>Ten en cuenta que normalmente simplemente llamaríamos a esta variable local <code>product</code>. Estamos usando
<code>my_product</code> para distinguirlo del nombre de la variable de instancia y el nombre de la plantilla
en este ejemplo.</p><p>Dado que <code>locals</code> es un hash, puedes pasar múltiples variables según sea necesario, como
<code>locals: { my_product: @product, my_reviews: @reviews }</code>.</p><p>Sin embargo, si una plantilla se refiere a una variable que <em>no</em> se pasa a la vista como
parte de la opción <code>locals:</code>, la plantilla generará un
<code>ActionView::Template::Error</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/products/_product.html.erb %></span>
<span class="cp"><%=</span> <span class="n">tag</span><span class="p">.</span><span class="nf">div</span> <span class="ss">id: </span><span class="n">dom_id</span><span class="p">(</span><span class="n">my_product</span><span class="p">)</span> <span class="k">do</span> <span class="cp">%></span>
<span class="nt"><h1></span><span class="cp"><%=</span> <span class="n">my_product</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%></span><span class="nt"></h1></span>
<span class="c"><%# => genera ActionView::Template::Error para `product_reviews` %></span>
<span class="cp"><%</span> <span class="n">product_reviews</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">review</span><span class="o">|</span> <span class="cp">%></span>
<span class="c"><%# ... %></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%= tag.div id: dom_id(my_product) do %>
<h1><%= my_product.name %></h1>
<%# => genera ActionView::Template::Error para `product_reviews` %>
<% product_reviews.each do |review| %>
<%# ... %>
<% end %>
<% end %>
">Copy</button>
</div>
<h3 id="usando-local-assigns"><a class="anchorlink" href="#usando-local-assigns"><span>4.4</span> Usando <code>local_assigns</code></a></h3><p>Cada parcial tiene un método llamado <a href="https://edgeapi.rubyonrails.org/classes/ActionView/Template.html#method-i-local_assigns">local_assigns</a> disponible. Puedes usar este
método para acceder a claves pasadas a través de la opción <code>locals:</code>. Si un parcial no fue
renderizado con <code>:some_key</code> establecido, el valor de <code>local_assigns[:some_key]</code> será
<code>nil</code> dentro del parcial.</p><p>Por ejemplo, <code>product_reviews</code> es <code>nil</code> en el siguiente ejemplo ya que solo
<code>product</code> está establecido en <code>locals:</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/products/show.html.erb %></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">product: </span><span class="vi">@product</span> <span class="p">}</span> <span class="cp">%></span>
<span class="c"><%# app/views/products/_product.html.erb %></span>
<span class="cp"><%</span> <span class="n">local_assigns</span><span class="p">[</span><span class="ss">:product</span><span class="p">]</span> <span class="c1"># => "#<Product:0x0000000109ec5d10>" </span><span class="cp">%></span>
<span class="cp"><%</span> <span class="n">local_assigns</span><span class="p">[</span><span class="ss">:product_reviews</span><span class="p">]</span> <span class="c1"># => nil </span><span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%= render partial: "product", locals: { product: @product } %>
<% local_assigns[:product] # => "#<Product:0x0000000109ec5d10>" %>
<% local_assigns[:product_reviews] # => nil %>
">Copy</button>
</div>
<p>Un caso de uso para <code>local_assigns</code> es pasar opcionalmente una variable local y
luego realizar condicionalmente una acción en el parcial basado en si la
variable local está establecida. Por ejemplo:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%</span> <span class="k">if</span> <span class="n">local_assigns</span><span class="p">[</span><span class="ss">:redirect</span><span class="p">]</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">form</span><span class="p">.</span><span class="nf">hidden_field</span> <span class="ss">:redirect</span><span class="p">,</span> <span class="ss">value: </span><span class="kp">true</span> <span class="cp">%></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<% if local_assigns[:redirect] %>
<%= form.hidden_field :redirect, value: true %>
<% end %>
">Copy</button>
</div>
<p>Otro ejemplo de <code>_blob.html.erb</code> de Active Storage. Este establece el tamaño
basado en si la variable local <code>in_gallery</code> está establecida al renderizar el
parcial que contiene esta línea:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">image_tag</span> <span class="n">blob</span><span class="p">.</span><span class="nf">representation</span><span class="p">(</span><span class="ss">resize_to_limit: </span><span class="n">local_assigns</span><span class="p">[</span><span class="ss">:in_gallery</span><span class="p">]</span> <span class="p">?</span> <span class="p">[</span> <span class="mi">800</span><span class="p">,</span> <span class="mi">600</span> <span class="p">]</span> <span class="p">:</span> <span class="p">[</span> <span class="mi">1024</span><span class="p">,</span> <span class="mi">768</span> <span class="p">])</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
">Copy</button>
</div>
<h3 id="render-sin-opciones-partial-y-locals"><a class="anchorlink" href="#render-sin-opciones-partial-y-locals"><span>4.5</span> <code>render</code> sin Opciones <code>partial</code> y <code>locals</code></a></h3><p>En los ejemplos anteriores, <code>render</code> toma 2 opciones: <code>partial</code> y <code>locals</code>. Pero si
estas son las únicas opciones que necesitas usar, puedes omitir las claves, <code>partial</code> y
<code>locals</code>, y especificar solo los valores.</p><p>Por ejemplo, en lugar de:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">product: </span><span class="vi">@product</span> <span class="p">}</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", locals: { product: @product } %>
">Copy</button>
</div>
<p>Puedes escribir:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="s2">"product"</span><span class="p">,</span> <span class="ss">product: </span><span class="vi">@product</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render "product", product: @product %>
">Copy</button>
</div>
<p>También puedes usar esta forma abreviada basada en convenciones:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="vi">@product</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render @product %>
">Copy</button>
</div>
<p>Esto buscará un parcial llamado <code>_product.html.erb</code> en <code>app/views/products/</code>,
así como pasar un local llamado <code>product</code> establecido en el valor <code>@product</code>.</p><h3 id="las-opciones-as-y-object"><a class="anchorlink" href="#las-opciones-as-y-object"><span>4.6</span> Las Opciones <code>as</code> y <code>object</code></a></h3><p>Por defecto, los objetos pasados a la plantilla están en una variable local con el mismo
nombre que la plantilla. Entonces, dado:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="vi">@product</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render @product %>
">Copy</button>
</div>
<p>dentro del parcial <code>_product.html.erb</code> obtendrás la variable de instancia <code>@product</code>
en la variable local <code>product</code>, como si hubieras escrito:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">product: </span><span class="vi">@product</span> <span class="p">}</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", locals: { product: @product } %>
">Copy</button>
</div>
<p>La opción <code>object</code> se puede usar para especificar un nombre diferente. Esto es útil cuando
el objeto de la plantilla está en otro lugar (por ejemplo, en una variable de instancia diferente o en una
variable local).</p><p>Por ejemplo, en lugar de:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">product: </span><span class="vi">@item</span> <span class="p">}</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", locals: { product: @item } %>
">Copy</button>
</div>
<p>puedes escribir:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">object: </span><span class="vi">@item</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", object: @item %>
">Copy</button>
</div>
<p>Esto asigna la variable de instancia <code>@item</code> a una variable local de parcial llamada
<code>product</code>. ¿Qué pasa si quisieras cambiar el nombre de la variable local del valor predeterminado
<code>product</code> a algo más? Puedes usar la opción <code>:as</code> para eso.</p><p>Con la opción <code>as</code>, puedes especificar un nombre diferente para la variable local
así:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">object: </span><span class="vi">@item</span><span class="p">,</span> <span class="ss">as: </span><span class="s2">"item"</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", object: @item, as: "item" %>
">Copy</button>
</div>
<p>Esto es equivalente a</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">item: </span><span class="vi">@item</span> <span class="p">}</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", locals: { item: @item } %>
">Copy</button>
</div>
<h3 id="renderizando-colecciones"><a class="anchorlink" href="#renderizando-colecciones"><span>4.7</span> Renderizando Colecciones</a></h3><p>Es común que una vista itere sobre una colección, como <code>@products</code>, y
renderice una plantilla parcial para cada objeto en la colección. Este patrón ha
sido implementado como un único método que acepta un array y renderiza un parcial
para cada uno de los elementos en el array.</p><p>Así que este ejemplo para renderizar todos los productos:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%</span> <span class="vi">@products</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">product</span><span class="o">|</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">product: </span><span class="n">product</span> <span class="p">}</span> <span class="cp">%></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<% @products.each do |product| %>
<%= render partial: "product", locals: { product: product } %>
<% end %>
">Copy</button>
</div>
<p>puede reescribirse en una sola línea:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">collection: </span><span class="vi">@products</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: "product", collection: @products %>
">Copy</button>
</div>
<p>Cuando un parcial se llama con una colección, las instancias individuales del
parcial tienen acceso al miembro de la colección que se está renderizando a través de una
variable nombrada después del parcial. En este caso, dado que el parcial es
<code>_product.html.erb</code>, puedes usar <code>product</code> para referirte al miembro de la colección
que se está renderizando.</p><p>También puedes usar la siguiente forma abreviada basada en convenciones para renderizar
colecciones.</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="vi">@products</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render @products %>
">Copy</button>
</div>
<p>Lo anterior asume que <code>@products</code> es una colección de instancias de <code>Product</code>. Rails
utiliza convenciones de nomenclatura para determinar el nombre del parcial a usar buscando
el nombre del modelo en la colección, <code>Product</code> en este caso. De hecho, incluso
puedes renderizar una colección compuesta por instancias de diferentes modelos usando esta
abreviatura, y Rails elegirá el parcial apropiado para cada miembro de la
colección.</p><h3 id="plantillas-de-espaciador"><a class="anchorlink" href="#plantillas-de-espaciador"><span>4.8</span> Plantillas de Espaciador</a></h3><p>También puedes especificar un segundo parcial para ser renderizado entre
instancias del parcial principal usando la opción <code>:spacer_template</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="vi">@products</span><span class="p">,</span> <span class="ss">spacer_template: </span><span class="s2">"product_ruler"</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: @products, spacer_template: "product_ruler" %>
">Copy</button>
</div>
<p>Rails renderizará el parcial <code>_product_ruler.html.erb</code> (sin pasarle datos) entre
cada par de parciales <code>_product.html.erb</code>.</p><h3 id="variables-de-contador"><a class="anchorlink" href="#variables-de-contador"><span>4.9</span> Variables de Contador</a></h3><p>Rails también hace disponible una variable de contador dentro de un parcial llamado por la
colección. La variable se nombra después del título del parcial seguido de
<code>_counter</code>. Por ejemplo, al renderizar una colección <code>@products</code> el parcial
<code>_product.html.erb</code> puede acceder a la variable <code>product_counter</code>. La variable
indexa el número de veces que el parcial ha sido renderizado dentro de la vista
envolvente, comenzando con un valor de <code>0</code> en la primera renderización.</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# index.html.erb %></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s2">"product"</span><span class="p">,</span> <span class="ss">collection: </span><span class="vi">@products</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%# index.html.erb %>
<%= render partial: "product", collection: @products %>
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# _product.html.erb %></span>
<span class="cp"><%=</span> <span class="n">product_counter</span> <span class="cp">%></span> # 0 para el primer producto, 1 para el segundo producto...
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%# _product.html.erb %>
<%= product_counter %> # 0 para el primer producto, 1 para el segundo producto...
">Copy</button>
</div>
<p>Esto también funciona cuando el nombre de la variable local se cambia usando la opción <code>as:</code>.
Así que si hiciste <code>as: :item</code>, la variable del contador sería <code>item_counter</code>.</p><p>Nota: Las siguientes dos secciones, <a href="#strict-locals">Locales Estrictos</a> y <a href="#local-assigns-with-pattern-matching">Asignaciones Locales con
Coincidencia de Patrones</a> son características más avanzadas
de usar parciales, incluidas aquí por completitud.</p><h3 id="local-assigns-con-coincidencia-de-patrones"><a class="anchorlink" href="#local-assigns-con-coincidencia-de-patrones"><span>4.10</span> <code>local_assigns</code> con Coincidencia de Patrones</a></h3><p>Dado que <code>local_assigns</code> es un <code>Hash</code>, es compatible con el <a href="https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html">operador de asignación de
coincidencia de patrones de Ruby 3.1</a>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">local_assigns</span> <span class="o">=></span> <span class="p">{</span> <span class="n">product</span><span class="p">:,</span> <span class="o">**</span><span class="n">options</span> <span class="p">}</span>
<span class="n">product</span> <span class="c1"># => "#<Product:0x0000000109ec5d10>"</span>
<span class="n">options</span> <span class="c1"># => {}</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="local_assigns => { product:, **options }
product # => "#<Product:0x0000000109ec5d10>"
options # => {}
">Copy</button>
</div>
<p>Cuando claves distintas de <code>:product</code> se asignan a una variable <code>Hash</code> local del
parcial, pueden ser expandidas en llamadas a métodos helper:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/products/_product.html.erb %></span>
<span class="cp"><%</span> <span class="n">local_assigns</span> <span class="o">=></span> <span class="p">{</span> <span class="n">product</span><span class="p">:,</span> <span class="o">**</span><span class="n">options</span> <span class="p">}</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">tag</span><span class="p">.</span><span class="nf">div</span> <span class="ss">id: </span><span class="n">dom_id</span><span class="p">(</span><span class="n">product</span><span class="p">),</span> <span class="o">**</span><span class="n">options</span> <span class="k">do</span> <span class="cp">%></span>
<span class="nt"><h1></span><span class="cp"><%=</span> <span class="n">product</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%></span><span class="nt"></h1></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="c"><%# app/views/products/show.html.erb %></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="s2">"products/product"</span><span class="p">,</span> <span class="ss">product: </span><span class="vi">@product</span><span class="p">,</span> <span class="ss">class: </span><span class="s2">"card"</span> <span class="cp">%></span>
<span class="c"><%# => <div id="product_1" class="card">
# <h1>Un widget</h1>
# </div>
%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<% local_assigns => { product:, **options } %>
<%= tag.div id: dom_id(product), **options do %>
<h1><%= product.name %></h1>
<% end %>
<%= render "products/product", product: @product, class: "card" %>
<%# => <div id="product_1" class="card">
# <h1>Un widget</h1>
# </div>
%>
">Copy</button>
</div>
<p>La asignación de coincidencia de patrones también admite el cambio de nombre de variables:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">local_assigns</span> <span class="o">=></span> <span class="p">{</span> <span class="ss">product: </span><span class="n">record</span> <span class="p">}</span>
<span class="n">product</span> <span class="c1"># => "#<Product:0x0000000109ec5d10>"</span>
<span class="n">record</span> <span class="c1"># => "#<Product:0x0000000109ec5d10>"</span>
<span class="n">product</span> <span class="o">==</span> <span class="n">record</span> <span class="c1"># => true</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="local_assigns => { product: record }
product # => "#<Product:0x0000000109ec5d10>"
record # => "#<Product:0x0000000109ec5d10>"
product == record # => true
">Copy</button>
</div>
<p>También puedes leer condicionalmente una variable y luego recurrir a un valor
predeterminado cuando la clave no es parte de las opciones <code>locals:</code>, usando <code>fetch</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/products/_product.html.erb %></span>
<span class="cp"><%</span> <span class="n">local_assigns</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="ss">:related_products</span><span class="p">,</span> <span class="p">[]).</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">related_product</span><span class="o">|</span> <span class="cp">%></span>
<span class="c"><%# ... %></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<% local_assigns.fetch(:related_products, []).each do |related_product| %>
<%# ... %>
<% end %>
">Copy</button>
</div>
<p>Combinar la asignación de coincidencia de patrones de Ruby 3.1 con llamadas a
<a href="https://edgeapi.rubyonrails.org/classes/Hash.html#method-i-with_defaults">Hash#with_defaults</a>
habilita asignaciones de variables locales de parcial predeterminadas compactas:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/products/_product.html.erb %></span>
<span class="cp"><%</span> <span class="n">local_assigns</span><span class="p">.</span><span class="nf">with_defaults</span><span class="p">(</span><span class="ss">related_products: </span><span class="p">[])</span> <span class="o">=></span> <span class="p">{</span> <span class="n">product</span><span class="p">:,</span> <span class="ss">related_products: </span><span class="p">}</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">tag</span><span class="p">.</span><span class="nf">div</span> <span class="ss">id: </span><span class="n">dom_id</span><span class="p">(</span><span class="n">product</span><span class="p">)</span> <span class="k">do</span> <span class="cp">%></span>
<span class="nt"><h1></span><span class="cp"><%=</span> <span class="n">product</span><span class="p">.</span><span class="nf">name</span> <span class="cp">%></span><span class="nt"></h1></span>
<span class="cp"><%</span> <span class="n">related_products</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">related_product</span><span class="o">|</span> <span class="cp">%></span>
<span class="c"><%# ... %></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
<span class="cp"><%</span> <span class="k">end</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<% local_assigns.with_defaults(related_products: []) => { product:, related_products: } %>
<%= tag.div id: dom_id(product) do %>
<h1><%= product.name %></h1>
<% related_products.each do |related_product| %>
<%# ... %>
<% end %>
<% end %>
">Copy</button>
</div>
<div class="interstitial info"><p>Por defecto, los parciales aceptarán cualquier <code>locals</code> como argumentos de palabra clave. Para
definir qué <code>locals</code> acepta un parcial, usa un comentario mágico <code>locals:</code>. Para
aprender más, lee sobre <a href="#strict-locals">Locales Estrictos</a>.</p></div><h3 id="locales-estrictos"><a class="anchorlink" href="#locales-estrictos"><span>4.11</span> Locales Estrictos</a></h3><p>Los parciales de Action View aceptarán cualquier número de <code>locals</code> como argumentos de palabra clave.
Puedes hacer cumplir cuántos y cuáles <code>locals</code> acepta una plantilla, establecer valores
predeterminados y más con un comentario mágico <code>locals:</code>.</p><p>Aquí hay algunos ejemplos del comentario mágico <code>locals:</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/messages/_message.html.erb %></span>
<span class="c"><%# locals: (message:) -%></span>
<span class="cp"><%=</span> <span class="n">message</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%# locals: (message:) -%>
<%= message %>
">Copy</button>
</div>
<p>Lo anterior hace que <code>message</code> sea una variable local requerida. Renderizar el parcial
sin un argumento de variable local <code>:message</code> generará una excepción:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">render</span> <span class="s2">"messages/message"</span>
<span class="c1"># => ActionView::Template::Error: falta local: :message para app/views/messages/_message.html.erb</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="render "messages/message"
# => ActionView::Template::Error: falta local: :message para app/views/messages/_message.html.erb
">Copy</button>
</div>
<p>Si se establece un valor predeterminado, entonces se puede usar si <code>message</code> no se pasa en
<code>locals:</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/messages/_message.html.erb %></span>
<span class="c"><%# locals: (message: "¡Hola, mundo!") -%></span>
<span class="cp"><%=</span> <span class="n">message</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%# locals: (message: "¡Hola, mundo!") -%>
<%= message %>
">Copy</button>
</div>
<p>Renderizar el parcial sin una variable local <code>:message</code> usa el valor predeterminado
establecido en el comentario mágico <code>locals:</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">render</span> <span class="s2">"messages/message"</span>
<span class="c1"># => "¡Hola, mundo!"</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="render "messages/message"
# => "¡Hola, mundo!"
">Copy</button>
</div>
<p>Renderizar el parcial con variables locales no especificadas en el comentario mágico
<code>local:</code> también generará una excepción:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">render</span> <span class="s2">"messages/message"</span><span class="p">,</span> <span class="ss">unknown_local: </span><span class="s2">"generará una excepción"</span>
<span class="c1"># => ActionView::Template::Error: local desconocido: :unknown_local para app/views/messages/_message.html.erb</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="render "messages/message", unknown_local: "generará una excepción"
# => ActionView::Template::Error: local desconocido: :unknown_local para app/views/messages/_message.html.erb
">Copy</button>
</div>
<p>Puedes permitir argumentos de variables locales opcionales con el operador de doble
asterisco <code>**</code>:</p><div class="interstitial code">
<pre><code class="highlight erb">
<span class="c"><%# app/views/messages/_message.html.erb %></span>
<span class="c"><%# locals: (message: "¡Hola, mundo!", **attributes) -%></span>
<span class="cp"><%=</span> <span class="n">tag</span><span class="p">.</span><span class="nf">p</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="o">**</span><span class="n">attributes</span><span class="p">)</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%# locals: (message: "¡Hola, mundo!", **attributes) -%>
<%= tag.p(message, **attributes) %>
">Copy</button>
</div>
<p>O puedes desactivar <code>locals</code> completamente estableciendo <code>locals:</code> en vacío <code>()</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/messages/_message.html.erb %></span>
<span class="c"><%# locals: () %></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="
<%# locals: () %>
">Copy</button>
</div>
<p>Renderizar el parcial con <em>cualquier</em> argumento de variable local generará una
excepción:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">render</span> <span class="s2">"messages/message"</span><span class="p">,</span> <span class="ss">unknown_local: </span><span class="s2">"generará una excepción"</span>
<span class="c1"># => ActionView::Template::Error: no se aceptan locales para app/views/messages/_message.html.erb</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="render "messages/message", unknown_local: "generará una excepción"
# => ActionView::Template::Error: no se aceptan locales para app/views/messages/_message.html.erb
">Copy</button>
</div>
<p>Action View procesará el comentario mágico <code>locals:</code> en cualquier motor de
plantillas que soporte comentarios prefijados con <code>#</code>, y leerá el comentario
mágico de cualquier línea en el parcial.</p><p>PRECAUCIÓN: Solo se admiten argumentos de palabra clave. Definir argumentos
posicionales o de bloque generará un Error de Action View en el momento de la
renderización.</p><p>El método <code>local_assigns</code> no contiene valores predeterminados especificados en el
comentario mágico <code>local:</code>. Para acceder a una variable local con un valor
predeterminado que tiene el mismo nombre que una palabra clave reservada de Ruby, como <code>class</code> o
<code>if</code>, los valores se pueden acceder a través de <code>binding.local_variable_get</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# locals: (class: "message") %></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"</span><span class="cp"><%=</span> <span class="nb">binding</span><span class="p">.</span><span class="nf">local_variable_get</span><span class="p">(</span><span class="ss">:class</span><span class="p">)</span> <span class="cp">%></span><span class="s">"</span><span class="nt">></span>...<span class="nt"></div></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%# locals: (class: "message") %>
<div class="<%= binding.local_variable_get(:class) %>">...</div>
">Copy</button>
</div>
<h2 id="diseños"><a class="anchorlink" href="#diseños"><span>5</span> Diseños</a></h2><p>Los diseños se pueden usar para renderizar una plantilla de vista común alrededor de los resultados de las
acciones del controlador de Rails. Una aplicación Rails puede tener múltiples diseños en los que se
pueden renderizar las páginas.</p><p>Por ejemplo, una aplicación podría tener un diseño para un usuario que ha iniciado sesión y
otro para la parte de marketing del sitio. El diseño del usuario que ha iniciado sesión podría
incluir navegación de nivel superior que debería estar presente en muchas acciones del
controlador. El diseño de ventas para una aplicación SaaS podría incluir navegación de nivel superior
para cosas como páginas de "Precios" y "Contáctenos". Los diferentes diseños pueden tener un
contenido de encabezado y pie de página diferente.</p><p>Para encontrar el diseño para la acción del controlador actual, Rails primero busca un
archivo en <code>app/views/layouts</code> con el mismo nombre base que el controlador. Por
ejemplo, renderizar acciones desde la clase <code>ProductsController</code> usará
<code>app/views/layouts/products.html.erb</code>.</p><p>Rails usará <code>app/views/layouts/application.html.erb</code> si no existe un diseño específico para el controlador.</p><p>Aquí hay un ejemplo de un diseño simple en el archivo <code>application.html.erb</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span><span class="cp"><%=</span> <span class="s2">"Tu Aplicación Rails"</span> <span class="cp">%></span><span class="nt"></title></span>
<span class="cp"><%=</span> <span class="n">csrf_meta_tags</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">csp_meta_tag</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">stylesheet_link_tag</span> <span class="s2">"application"</span><span class="p">,</span> <span class="s2">"data-turbo-track"</span><span class="p">:</span> <span class="s2">"reload"</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">javascript_importmap_tags</span> <span class="cp">%></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><nav></span>
<span class="nt"><ul></span>
<span class="nt"><li></span><span class="cp"><%=</span> <span class="n">link_to</span> <span class="s2">"Inicio"</span><span class="p">,</span> <span class="n">root_path</span> <span class="cp">%></span><span class="nt"></li></span>
<span class="nt"><li></span><span class="cp"><%=</span> <span class="n">link_to</span> <span class="s2">"Productos"</span><span class="p">,</span> <span class="n">products_path</span> <span class="cp">%></span><span class="nt"></li></span>
<span class="c"><!-- Enlaces de navegación adicionales aquí --></span>
<span class="nt"></ul></span>
<span class="nt"></nav></span>
<span class="cp"><%=</span> <span class="k">yield</span> <span class="cp">%></span>
<span class="nt"><footer></span>
<span class="nt"><p></span><span class="ni">&copy;</span> <span class="cp"><%=</span> <span class="no">Date</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">year</span> <span class="cp">%></span> Tu Empresa<span class="nt"></p></span>
<span class="nt"></footer></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<!DOCTYPE html>
<html>
<head>
<title><%= "Tu Aplicación Rails" %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<body>
<nav>
<ul>
<li><%= link_to "Inicio", root_path %></li>
<li><%= link_to "Productos", products_path %></li>
<!-- Enlaces de navegación adicionales aquí -->
</ul>
</nav>
<%= yield %>
<footer>
<p>&copy; <%= Date.current.year %> Tu Empresa</p>
</footer>
">Copy</button>
</div>
<p>En el ejemplo de diseño anterior, el contenido de la vista se renderizará en lugar de <code><%=
yield %></code>, y estará rodeado por el mismo contenido de <code><head></code>, <code><nav></code> y <code><footer></code>.</p><p>Rails proporciona más formas de asignar diseños específicos a controladores y
acciones individuales. Puedes aprender más sobre los diseños en general en la guía
<a href="layouts_and_rendering.html">Layouts y Renderizado en Rails</a>.</p><h3 id="diseños-parciales"><a class="anchorlink" href="#diseños-parciales"><span>5.1</span> Diseños Parciales</a></h3><p>Los parciales pueden tener sus propios diseños aplicados a ellos. Estos diseños son diferentes
de los aplicados a una acción del controlador, pero funcionan de manera similar.</p><p>Digamos que estás mostrando un artículo en una página que debería estar envuelto en un
<code>div</code> para fines de presentación. Primero, crearás un nuevo <code>Article</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="no">Article</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">body: </span><span class="s1">'¡Los Diseños Parciales son geniales!'</span><span class="p">)</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Article.create(body: '¡Los Diseños Parciales son geniales!')
">Copy</button>
</div>
<p>En la plantilla <code>show</code>, renderizarás el parcial <code>_article</code> envuelto en el
diseño <code>box</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/articles/show.html.erb %></span>
<span class="cp"><%=</span> <span class="n">render</span> <span class="ss">partial: </span><span class="s1">'article'</span><span class="p">,</span> <span class="ss">layout: </span><span class="s1">'box'</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">article: </span><span class="vi">@article</span> <span class="p">}</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= render partial: 'article', layout: 'box', locals: { article: @article } %>
">Copy</button>
</div>
<p>El diseño <code>box</code> simplemente envuelve el parcial <code>_article</code> en un <code>div</code>:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/articles/_box.html.erb %></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"box"</span><span class="nt">></span>
<span class="cp"><%=</span> <span class="k">yield</span> <span class="cp">%></span>
<span class="nt"></div></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<div class="box">
<%= yield %>
</div>
">Copy</button>
</div>
<p>Ten en cuenta que el diseño parcial tiene acceso a la variable local <code>article</code> que fue
pasada en la llamada a <code>render</code>, aunque no se está utilizando dentro de
<code>_box.html.erb</code> en este caso.</p><p>A diferencia de los diseños a nivel de aplicación, los diseños parciales aún tienen el prefijo de guion bajo
en su nombre.</p><p>También puedes renderizar un bloque de código dentro de un diseño parcial en lugar de llamar a
<code>yield</code>. Por ejemplo, si no tuvieras el parcial <code>_article</code>, podrías hacer
esto en su lugar:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="c"><%# app/views/articles/show.html.erb %></span>
<span class="cp"><%=</span> <span class="n">render</span><span class="p">(</span><span class="ss">layout: </span><span class="s1">'box'</span><span class="p">,</span> <span class="ss">locals: </span><span class="p">{</span> <span class="ss">article: </span><span class="vi">@article</span> <span class="p">})</span> <span class="k">do</span> <span class="cp">%></span>
<span class="nt"><div></span>
<span class="nt"><p></span><span class="cp"><%=</span> <span class="n">article</span><span class="p">.</span><span class="nf">body</span> <span class="cp">%></span><span class="nt"></p></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="<%= render(layout: 'box', locals: { article: @article }) do %>
<div>
<p><%= article.body %></p>
</div>
<% end %>
">Copy</button>
</div>