-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrouting.html
2134 lines (2076 loc) · 149 KB
/
routing.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>Rutas de Rails desde el Exterior hacia el Interior — 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="Rutas de Rails desde el Exterior hacia el Interior — Ruby on Rails Guides" />
<meta name="description" content="NO LEAS ESTE ARCHIVO EN GITHUB, LAS GUÍAS SE PUBLICAN EN https://guides.rubyonrails.org.Rutas de Rails desde el Exterior hacia el InteriorEsta guía cubre las características de las rutas de Rails orientadas al usuario.Después de leer esta guía, sabrás: Cómo interpretar el código en config/routes.rb. Cómo construir tus propias rutas, usando el estilo preferido de recursos o el método match. Cómo declarar parámetros de ruta, que se pasan a las acciones del controlador. Cómo crear automáticamente rutas y URLs usando los helpers de ruta. Técnicas avanzadas como crear restricciones y montar endpoints Rack." />
<meta property="og:description" content="NO LEAS ESTE ARCHIVO EN GITHUB, LAS GUÍAS SE PUBLICAN EN https://guides.rubyonrails.org.Rutas de Rails desde el Exterior hacia el InteriorEsta guía cubre las características de las rutas de Rails orientadas al usuario.Después de leer esta guía, sabrás: Cómo interpretar el código en config/routes.rb. Cómo construir tus propias rutas, usando el estilo preferido de recursos o el método match. Cómo declarar parámetros de ruta, que se pasan a las acciones del controlador. Cómo crear automáticamente rutas y URLs usando los helpers de ruta. Técnicas avanzadas como crear restricciones y montar endpoints Rack." />
<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 LEAS ESTE ARCHIVO EN GITHUB, LAS GUÍAS SE PUBLICAN EN <a href="https://guides.rubyonrails.org">https://guides.rubyonrails.org</a>.</strong></p><h1>Rutas de Rails desde el Exterior hacia el Interior</h1><p>Esta guía cubre las características de las rutas de Rails orientadas al usuario.</p><p>Después de leer esta guía, sabrás:</p>
<ul>
<li>Cómo interpretar el código en <code>config/routes.rb</code>.</li>
<li>Cómo construir tus propias rutas, usando el estilo preferido de recursos o el método <code>match</code>.</li>
<li>Cómo declarar parámetros de ruta, que se pasan a las acciones del controlador.</li>
<li>Cómo crear automáticamente rutas y URLs usando los helpers de ruta.</li>
<li>Técnicas avanzadas como crear restricciones y montar endpoints Rack.</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="#el-propósito-del-router-de-rails">El Propósito del Router de Rails</a>
<ul>
<li><a href="#conectando-urls-al-código">Conectando URLs al Código</a></li>
<li><a href="#generando-rutas-y-urls-desde-el-código">Generando Rutas y URLs desde el Código</a></li>
<li><a href="#configurando-el-router-de-rails">Configurando el Router de Rails</a></li>
</ul></li>
<li><a href="#rutas-de-recursos-el-predeterminado-de-rails">Rutas de Recursos: el Predeterminado de Rails</a>
<ul>
<li><a href="#recursos-en-la-web">Recursos en la Web</a></li>
<li><a href="#crud-verbos-y-acciones">CRUD, Verbos y Acciones</a></li>
<li><a href="#helpers-de-ruta-y-url">Helpers de Ruta y URL</a></li>
<li><a href="#definiendo-múltiples-recursos-al-mismo-tiempo">Definiendo Múltiples Recursos al Mismo Tiempo</a></li>
<li><a href="#recursos-singulares">Recursos Singulares</a></li>
<li><a href="#nombres-de-controladores-y-rutas">Nombres de Controladores y Rutas</a></li>
<li><a href="#recursos-anidados">Recursos Anidados</a></li>
<li><a href="#preocupaciones-de-enrutamiento">Preocupaciones de Enrutamiento</a></li>
<li><a href="#creando-rutas-y-urls-desde-objetos">Creando Rutas y URLs desde Objetos</a></li>
<li><a href="#agregando-más-acciones-restful">Agregando Más Acciones RESTful</a></li>
</ul></li>
<li><a href="#rutas-no-resursivas">Rutas No-Resursivas</a>
<ul>
<li><a href="#parámetros-vinculados">Parámetros Vinculados</a></li>
<li><a href="#segmentos-dinámicos">Segmentos Dinámicos</a></li>
<li><a href="#segmentos-estáticos">Segmentos Estáticos</a></li>
<li><a href="#la-cadena-de-consulta">La Cadena de Consulta</a></li>
<li><a href="#definiendo-valores-predeterminados">Definiendo Valores Predeterminados</a></li>
<li><a href="#nombrando-rutas">Nombrando Rutas</a></li>
<li><a href="#restricciones-de-verbos-http">Restricciones de Verbos HTTP</a></li>
<li><a href="#restricciones-de-segmentos">Restricciones de Segmentos</a></li>
<li><a href="#restricciones-basadas-en-solicitudes">Restricciones Basadas en Solicitudes</a></li>
<li><a href="#restricciones-avanzadas">Restricciones Avanzadas</a></li>
<li><a href="#globbing-de-rutas-y-segmentos-comodín">Globbing de Rutas y Segmentos Comodín</a></li>
<li><a href="#redirección">Redirección</a></li>
<li><a href="#enrutando-a-aplicaciones-rack">Enrutando a Aplicaciones Rack</a></li>
<li><a href="#usando-root">Usando <code>root</code></a></li>
<li><a href="#rutas-de-caracteres-unicode">Rutas de Caracteres Unicode</a></li>
<li><a href="#rutas-directas">Rutas Directas</a></li>
<li><a href="#usando-resolve">Usando <code>resolve</code></a></li>
</ul></li>
<li><a href="#personalizando-rutas-de-recursos">Personalizando Rutas de Recursos</a>
<ul>
<li><a href="#especificando-un-controlador-a-usar">Especificando un Controlador a Usar</a></li>
<li><a href="#especificando-restricciones">Especificando Restricciones</a></li>
<li><a href="#anulando-los-helpers-de-ruta-nombrada">Anulando los Helpers de Ruta Nombrada</a></li>
<li><a href="#anulando-los-segmentos-new-y-edit">Anulando los Segmentos <code>new</code> y <code>edit</code></a></li>
<li><a href="#prefijando-los-helpers-de-ruta-nombrada">Prefijando los Helpers de Ruta Nombrada</a></li>
<li><a href="#restringiendo-las-rutas-creadas">Restringiendo las Rutas Creadas</a></li>
<li><a href="#rutas-traducidas">Rutas Traducidas</a></li>
<li><a href="#anulando-la-forma-singular">Anulando la Forma Singular</a></li>
<li><a href="#usando-as-en-recursos-anidados">Usando <code>:as</code> en Recursos Anidados</a></li>
<li><a href="#anulando-parámetros-de-ruta-nombrados">Anulando Parámetros de Ruta Nombrados</a></li>
</ul></li>
<li><a href="#dividiendo-un-archivo-de-rutas-muy-grande-en-múltiples-archivos-pequeños">Dividiendo un Archivo de Rutas <em>Muy</em> Grande en Múltiples Archivos Pequeños</a>
<ul>
<li><a href="#no-uses-esta-función-a-menos-que-realmente-la-necesites">No Uses Esta Función a Menos que Realmente la Necesites</a></li>
</ul></li>
<li><a href="#inspeccionando-y-probando-rutas">Inspeccionando y Probando Rutas</a>
<ul>
<li><a href="#listando-rutas-existentes">Listando Rutas Existentes</a></li>
<li><a href="#probando-rutas">Probando Rutas</a></li>
</ul></li>
</ol>
</nav>
<hr>
</div>
</section>
<main id="container">
<div class="wrapper">
<div id="mainCol">
<h2 id="el-propósito-del-router-de-rails"><a class="anchorlink" href="#el-propósito-del-router-de-rails"><span>1</span> El Propósito del Router de Rails</a></h2><p>El router de Rails reconoce URLs y las envía a la acción de un controlador, o a una aplicación Rack. También puede generar rutas y URLs, evitando la necesidad de codificar cadenas en tus vistas.</p><h3 id="conectando-urls-al-código"><a class="anchorlink" href="#conectando-urls-al-código"><span>1.1</span> Conectando URLs al Código</a></h3><p>Cuando tu aplicación Rails recibe una solicitud entrante para:</p><div class="interstitial code">
<pre><code class="highlight plaintext">GET /patients/17
</code></pre>
<button class="clipboard-button" data-clipboard-text="GET /patients/17
">Copy</button>
</div>
<p>le pide al router que la empareje con una acción del controlador. Si la primera ruta coincidente es:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">get</span> <span class="s1">'/patients/:id'</span><span class="p">,</span> <span class="ss">to: </span><span class="s1">'patients#show'</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="get '/patients/:id', to: 'patients#show'
">Copy</button>
</div>
<p>la solicitud se envía a la acción <code>show</code> del controlador <code>patients</code> con <code>{ id: '17' }</code> en <code>params</code>.</p><p>NOTA: Rails usa snake_case para los nombres de los controladores aquí, si tienes un controlador de varias palabras como <code>MonsterTrucksController</code>, querrás usar <code>monster_trucks#show</code> por ejemplo.</p><h3 id="generando-rutas-y-urls-desde-el-código"><a class="anchorlink" href="#generando-rutas-y-urls-desde-el-código"><span>1.2</span> Generando Rutas y URLs desde el Código</a></h3><p>También puedes generar rutas y URLs. Si la ruta anterior se modifica para ser:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">get</span> <span class="s1">'/patients/:id'</span><span class="p">,</span> <span class="ss">to: </span><span class="s1">'patients#show'</span><span class="p">,</span> <span class="ss">as: </span><span class="s1">'patient'</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="get '/patients/:id', to: 'patients#show', as: 'patient'
">Copy</button>
</div>
<p>y tu aplicación contiene este código en el controlador:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="vi">@patient</span> <span class="o">=</span> <span class="no">Patient</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>
</code></pre>
<button class="clipboard-button" data-clipboard-text="@patient = Patient.find(params[:id])
">Copy</button>
</div>
<p>y esto en la vista correspondiente:</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">link_to</span> <span class="s1">'Patient Record'</span><span class="p">,</span> <span class="n">patient_path</span><span class="p">(</span><span class="vi">@patient</span><span class="p">)</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= link_to 'Patient Record', patient_path(@patient) %>
">Copy</button>
</div>
<p>entonces el router generará la ruta <code>/patients/17</code>. Esto reduce la fragilidad de tu vista y hace que tu código sea más fácil de entender. Ten en cuenta que el id no necesita ser especificado en el helper de la ruta.</p><h3 id="configurando-el-router-de-rails"><a class="anchorlink" href="#configurando-el-router-de-rails"><span>1.3</span> Configurando el Router de Rails</a></h3><p>Las rutas para tu aplicación o motor viven en el archivo <code>config/routes.rb</code> y típicamente se ven así:</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">resources</span> <span class="ss">:brands</span><span class="p">,</span> <span class="ss">only: </span><span class="p">[</span><span class="ss">:index</span><span class="p">,</span> <span class="ss">:show</span><span class="p">]</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:products</span><span class="p">,</span> <span class="ss">only: </span><span class="p">[</span><span class="ss">:index</span><span class="p">,</span> <span class="ss">:show</span><span class="p">]</span>
<span class="k">end</span>
<span class="n">resource</span> <span class="ss">:basket</span><span class="p">,</span> <span class="ss">only: </span><span class="p">[</span><span class="ss">:show</span><span class="p">,</span> <span class="ss">:update</span><span class="p">,</span> <span class="ss">:destroy</span><span class="p">]</span>
<span class="n">resolve</span><span class="p">(</span><span class="s2">"Basket"</span><span class="p">)</span> <span class="p">{</span> <span class="n">route_for</span><span class="p">(</span><span class="ss">:basket</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Rails.application.routes.draw do
resources :brands, only: [:index, :show] do
resources :products, only: [:index, :show]
end
resource :basket, only: [:show, :update, :destroy]
resolve("Basket") { route_for(:basket) }
end
">Copy</button>
</div>
<p>Dado que este es un archivo fuente Ruby regular, puedes usar todas sus características para ayudarte a definir tus rutas, pero ten cuidado con los nombres de las variables ya que pueden chocar con los métodos DSL del router.</p><p>NOTA: El bloque <code>Rails.application.routes.draw do ... end</code> que envuelve tus definiciones de ruta es necesario para establecer el alcance del DSL del router y no debe ser eliminado.</p><h2 id="rutas-de-recursos-el-predeterminado-de-rails"><a class="anchorlink" href="#rutas-de-recursos-el-predeterminado-de-rails"><span>2</span> Rutas de Recursos: el Predeterminado de Rails</a></h2><p>Las rutas de recursos te permiten declarar rápidamente todas las rutas comunes para un controlador de recursos dado. Una sola llamada a <a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-resources"><code>resources</code></a> puede declarar todas las rutas necesarias para tus acciones <code>index</code>, <code>show</code>, <code>new</code>, <code>edit</code>, <code>create</code>, <code>update</code> y <code>destroy</code>.</p><h3 id="recursos-en-la-web"><a class="anchorlink" href="#recursos-en-la-web"><span>2.1</span> Recursos en la Web</a></h3><p>Los navegadores solicitan páginas de Rails haciendo una solicitud para una URL usando un método HTTP específico, como <code>GET</code>, <code>POST</code>, <code>PATCH</code>, <code>PUT</code> y <code>DELETE</code>. Cada método es una solicitud para realizar una operación en el recurso. Una ruta de recurso mapea una serie de solicitudes relacionadas a acciones en un solo controlador.</p><p>Cuando tu aplicación Rails recibe una solicitud entrante para:</p><div class="interstitial code">
<pre><code class="highlight plaintext">DELETE /photos/17
</code></pre>
<button class="clipboard-button" data-clipboard-text="DELETE /photos/17
">Copy</button>
</div>
<p>le pide al router que la mapee a una acción del controlador. Si la primera ruta coincidente es:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:photos</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :photos
">Copy</button>
</div>
<p>Rails enviaría esa solicitud a la acción <code>destroy</code> en el controlador <code>photos</code> con <code>{ id: '17' }</code> en <code>params</code>.</p><h3 id="crud-verbos-y-acciones"><a class="anchorlink" href="#crud-verbos-y-acciones"><span>2.2</span> CRUD, Verbos y Acciones</a></h3><p>En Rails, una ruta de recurso proporciona un mapeo entre verbos HTTP y URLs a acciones del controlador. Por convención, cada acción también se mapea a una operación CRUD específica en una base de datos. Una sola entrada en el archivo de rutas, como:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:photos</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :photos
">Copy</button>
</div>
<p>crea siete rutas diferentes en tu aplicación, todas mapeando al controlador <code>Photos</code>:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Usado para</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/photos</td>
<td>photos#index</td>
<td>mostrar una lista de todas las fotos</td>
</tr>
<tr>
<td>GET</td>
<td>/photos/new</td>
<td>photos#new</td>
<td>devolver un formulario HTML para crear una nueva foto</td>
</tr>
<tr>
<td>POST</td>
<td>/photos</td>
<td>photos#create</td>
<td>crear una nueva foto</td>
</tr>
<tr>
<td>GET</td>
<td>/photos/:id</td>
<td>photos#show</td>
<td>mostrar una foto específica</td>
</tr>
<tr>
<td>GET</td>
<td>/photos/:id/edit</td>
<td>photos#edit</td>
<td>devolver un formulario HTML para editar una foto</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/photos/:id</td>
<td>photos#update</td>
<td>actualizar una foto específica</td>
</tr>
<tr>
<td>DELETE</td>
<td>/photos/:id</td>
<td>photos#destroy</td>
<td>eliminar una foto específica</td>
</tr>
</tbody></table>
<p>NOTA: Debido a que el router usa el verbo HTTP y la URL para emparejar solicitudes entrantes, cuatro URLs se mapean a siete acciones diferentes.</p><p>NOTA: Las rutas de Rails se emparejan en el orden en que se especifican, por lo que si tienes un <code>resources :photos</code> encima de un <code>get 'photos/poll'</code>, la ruta de la acción <code>show</code> para la línea <code>resources</code> se emparejará antes que la línea <code>get</code>. Para solucionar esto, mueve la línea <code>get</code> <strong>encima</strong> de la línea <code>resources</code> para que se empareje primero.</p><h3 id="helpers-de-ruta-y-url"><a class="anchorlink" href="#helpers-de-ruta-y-url"><span>2.3</span> Helpers de Ruta y URL</a></h3><p>Crear una ruta de recurso también expondrá una serie de helpers a los controladores en tu aplicación. En el caso de <code>resources :photos</code>:</p>
<ul>
<li><code>photos_path</code> devuelve <code>/photos</code></li>
<li><code>new_photo_path</code> devuelve <code>/photos/new</code></li>
<li><code>edit_photo_path(:id)</code> devuelve <code>/photos/:id/edit</code> (por ejemplo, <code>edit_photo_path(10)</code> devuelve <code>/photos/10/edit</code>)</li>
<li><code>photo_path(:id)</code> devuelve <code>/photos/:id</code> (por ejemplo, <code>photo_path(10)</code> devuelve <code>/photos/10</code>)</li>
</ul>
<p>Cada uno de estos helpers tiene un helper <code>_url</code> correspondiente (como <code>photos_url</code>) que devuelve la misma ruta con el prefijo del host, puerto y prefijo de ruta actuales.</p><p>CONSEJO: Para encontrar los nombres de los helpers de ruta para tus rutas, consulta <a href="#listado-de-rutas-existentes">Listado de rutas existentes</a> a continuación.</p><h3 id="definiendo-múltiples-recursos-al-mismo-tiempo"><a class="anchorlink" href="#definiendo-múltiples-recursos-al-mismo-tiempo"><span>2.4</span> Definiendo Múltiples Recursos al Mismo Tiempo</a></h3><p>Si necesitas crear rutas para más de un recurso, puedes ahorrar un poco de escritura definiéndolos todos con una sola llamada a <code>resources</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:photos</span><span class="p">,</span> <span class="ss">:books</span><span class="p">,</span> <span class="ss">:videos</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :photos, :books, :videos
">Copy</button>
</div>
<p>Esto funciona exactamente igual que:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:photos</span>
<span class="n">resources</span> <span class="ss">:books</span>
<span class="n">resources</span> <span class="ss">:videos</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :photos
resources :books
resources :videos
">Copy</button>
</div>
<h3 id="recursos-singulares"><a class="anchorlink" href="#recursos-singulares"><span>2.5</span> Recursos Singulares</a></h3><p>A veces, tienes un recurso que los clientes siempre buscan sin hacer referencia a un ID. Por ejemplo, te gustaría que <code>/profile</code> siempre muestre el perfil del usuario actualmente conectado. En este caso, puedes usar un recurso singular para mapear <code>/profile</code> (en lugar de <code>/profile/:id</code>) a la acción <code>show</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">get</span> <span class="s1">'profile'</span><span class="p">,</span> <span class="ss">to: </span><span class="s1">'users#show'</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="get 'profile', to: 'users#show'
">Copy</button>
</div>
<p>Pasar una <code>String</code> a <code>to:</code> esperará un formato <code>controller#action</code>. Al usar un <code>Symbol</code>, la opción <code>to:</code> debe ser reemplazada con <code>action:</code>. Al usar una <code>String</code> sin un <code>#</code>, la opción <code>to:</code> debe ser reemplazada con <code>controller:</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">get</span> <span class="s1">'profile'</span><span class="p">,</span> <span class="ss">action: :show</span><span class="p">,</span> <span class="ss">controller: </span><span class="s1">'users'</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="get 'profile', action: :show, controller: 'users'
">Copy</button>
</div>
<p>Esta ruta de recurso:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resource</span> <span class="ss">:geocoder</span>
<span class="n">resolve</span><span class="p">(</span><span class="s1">'Geocoder'</span><span class="p">)</span> <span class="p">{</span> <span class="p">[</span><span class="ss">:geocoder</span><span class="p">]</span> <span class="p">}</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resource :geocoder
resolve('Geocoder') { [:geocoder] }
">Copy</button>
</div>
<p>crea seis rutas diferentes en tu aplicación, todas mapeando al controlador <code>Geocoders</code>:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Usado para</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/geocoder/new</td>
<td>geocoders#new</td>
<td>devolver un formulario HTML para crear el geocoder</td>
</tr>
<tr>
<td>POST</td>
<td>/geocoder</td>
<td>geocoders#create</td>
<td>crear el nuevo geocoder</td>
</tr>
<tr>
<td>GET</td>
<td>/geocoder</td>
<td>geocoders#show</td>
<td>mostrar el único recurso geocoder</td>
</tr>
<tr>
<td>GET</td>
<td>/geocoder/edit</td>
<td>geocoders#edit</td>
<td>devolver un formulario HTML para editar el geocoder</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/geocoder</td>
<td>geocoders#update</td>
<td>actualizar el único recurso geocoder</td>
</tr>
<tr>
<td>DELETE</td>
<td>/geocoder</td>
<td>geocoders#destroy</td>
<td>eliminar el recurso geocoder</td>
</tr>
</tbody></table>
<p>NOTA: Debido a que podrías querer usar el mismo controlador para una ruta singular (<code>/account</code>) y una ruta plural (<code>/accounts/45</code>), los recursos singulares se mapean a controladores plurales. Así que, por ejemplo, <code>resource :photo</code> y <code>resources :photos</code> crean tanto rutas singulares como plurales que se mapean al mismo controlador (<code>PhotosController</code>).</p><p>Una ruta de recurso singular genera estos helpers:</p>
<ul>
<li><code>new_geocoder_path</code> devuelve <code>/geocoder/new</code></li>
<li><code>edit_geocoder_path</code> devuelve <code>/geocoder/edit</code></li>
<li><code>geocoder_path</code> devuelve <code>/geocoder</code></li>
</ul>
<p>NOTA: La llamada a <code>resolve</code> es necesaria para convertir instancias del <code>Geocoder</code> a rutas a través de <a href="form_helpers.html#relying-on-record-identification">identificación de registro</a>.</p><p>Al igual que con los recursos plurales, los mismos helpers que terminan en <code>_url</code> también incluirán el host, puerto y prefijo de ruta.</p><h3 id="nombres-de-controladores-y-rutas"><a class="anchorlink" href="#nombres-de-controladores-y-rutas"><span>2.6</span> Nombres de Controladores y Rutas</a></h3><p>Es posible que desees organizar grupos de controladores bajo un namespace. Más comúnmente, podrías agrupar varios controladores administrativos bajo un namespace <code>Admin::</code>, y colocar estos controladores bajo el directorio <code>app/controllers/admin</code>. Puedes enrutar a tal grupo usando un bloque <a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-namespace"><code>namespace</code></a>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">namespace</span> <span class="ss">:admin</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:articles</span><span class="p">,</span> <span class="ss">:comments</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="namespace :admin do
resources :articles, :comments
end
">Copy</button>
</div>
<p>Esto creará una serie de rutas para cada uno de los controladores <code>articles</code> y <code>comments</code>. Para <code>Admin::ArticlesController</code>, Rails creará:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Helper de Ruta Nombrada</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/admin/articles</td>
<td>admin/articles#index</td>
<td>admin_articles_path</td>
</tr>
<tr>
<td>GET</td>
<td>/admin/articles/new</td>
<td>admin/articles#new</td>
<td>new_admin_article_path</td>
</tr>
<tr>
<td>POST</td>
<td>/admin/articles</td>
<td>admin/articles#create</td>
<td>admin_articles_path</td>
</tr>
<tr>
<td>GET</td>
<td>/admin/articles/:id</td>
<td>admin/articles#show</td>
<td>admin_article_path(:id)</td>
</tr>
<tr>
<td>GET</td>
<td>/admin/articles/:id/edit</td>
<td>admin/articles#edit</td>
<td>edit_admin_article_path(:id)</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/admin/articles/:id</td>
<td>admin/articles#update</td>
<td>admin_article_path(:id)</td>
</tr>
<tr>
<td>DELETE</td>
<td>/admin/articles/:id</td>
<td>admin/articles#destroy</td>
<td>admin_article_path(:id)</td>
</tr>
</tbody></table>
<p>Si en cambio quieres enrutar <code>/articles</code> (sin el prefijo <code>/admin</code>) a <code>Admin::ArticlesController</code>, puedes especificar el módulo con un bloque <a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Scoping.html#method-i-scope"><code>scope</code></a>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">scope</span> <span class="ss">module: </span><span class="s1">'admin'</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:articles</span><span class="p">,</span> <span class="ss">:comments</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="scope module: 'admin' do
resources :articles, :comments
end
">Copy</button>
</div>
<p>Esto también se puede hacer para una sola ruta:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:articles</span><span class="p">,</span> <span class="ss">module: </span><span class="s1">'admin'</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :articles, module: 'admin'
">Copy</button>
</div>
<p>Si en cambio quieres enrutar <code>/admin/articles</code> a <code>ArticlesController</code> (sin el prefijo de módulo <code>Admin::</code>), puedes especificar la ruta con un bloque <code>scope</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">scope</span> <span class="s1">'/admin'</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:articles</span><span class="p">,</span> <span class="ss">:comments</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="scope '/admin' do
resources :articles, :comments
end
">Copy</button>
</div>
<p>Esto también se puede hacer para una sola ruta:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:articles</span><span class="p">,</span> <span class="ss">path: </span><span class="s1">'/admin/articles'</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :articles, path: '/admin/articles'
">Copy</button>
</div>
<p>En ambos casos, los helpers de ruta nombrados permanecen iguales como si no hubieras usado <code>scope</code>. En el último caso, las siguientes rutas se mapean a <code>ArticlesController</code>:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Helper de Ruta Nombrada</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/admin/articles</td>
<td>articles#index</td>
<td>articles_path</td>
</tr>
<tr>
<td>GET</td>
<td>/admin/articles/new</td>
<td>articles#new</td>
<td>new_article_path</td>
</tr>
<tr>
<td>POST</td>
<td>/admin/articles</td>
<td>articles#create</td>
<td>articles_path</td>
</tr>
<tr>
<td>GET</td>
<td>/admin/articles/:id</td>
<td>articles#show</td>
<td>article_path(:id)</td>
</tr>
<tr>
<td>GET</td>
<td>/admin/articles/:id/edit</td>
<td>articles#edit</td>
<td>edit_article_path(:id)</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/admin/articles/:id</td>
<td>articles#update</td>
<td>article_path(:id)</td>
</tr>
<tr>
<td>DELETE</td>
<td>/admin/articles/:id</td>
<td>articles#destroy</td>
<td>article_path(:id)</td>
</tr>
</tbody></table>
<p>CONSEJO: Si necesitas usar un namespace de controlador diferente dentro de un bloque <code>namespace</code>, puedes especificar una ruta de controlador absoluta, por ejemplo: <code>get '/foo', to: '/foo#index'</code>.</p><h3 id="recursos-anidados"><a class="anchorlink" href="#recursos-anidados"><span>2.7</span> Recursos Anidados</a></h3><p>Es común tener recursos que son lógicamente hijos de otros recursos. Por ejemplo, supongamos que tu aplicación incluye estos modelos:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Magazine</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">has_many</span> <span class="ss">:ads</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Ad</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">belongs_to</span> <span class="ss">:magazine</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Magazine < ApplicationRecord
has_many :ads
end
class Ad < ApplicationRecord
belongs_to :magazine
end
">Copy</button>
</div>
<p>Las rutas anidadas te permiten capturar esta relación en tu enrutamiento. En este caso, podrías incluir esta declaración de ruta:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:magazines</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:ads</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :magazines do
resources :ads
end
">Copy</button>
</div>
<p>Además de las rutas para revistas, esta declaración también enviará anuncios a un <code>AdsController</code>. Las URLs de anuncios requieren una revista:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Usado para</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/magazines/:magazine_id/ads</td>
<td>ads#index</td>
<td>mostrar una lista de todos los anuncios para una revista específica</td>
</tr>
<tr>
<td>GET</td>
<td>/magazines/:magazine_id/ads/new</td>
<td>ads#new</td>
<td>devolver un formulario HTML para crear un nuevo anuncio para una revista específica</td>
</tr>
<tr>
<td>POST</td>
<td>/magazines/:magazine_id/ads</td>
<td>ads#create</td>
<td>crear un nuevo anuncio para una revista específica</td>
</tr>
<tr>
<td>GET</td>
<td>/magazines/:magazine_id/ads/:id</td>
<td>ads#show</td>
<td>mostrar un anuncio específico para una revista específica</td>
</tr>
<tr>
<td>GET</td>
<td>/magazines/:magazine_id/ads/:id/edit</td>
<td>ads#edit</td>
<td>devolver un formulario HTML para editar un anuncio para una revista específica</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/magazines/:magazine_id/ads/:id</td>
<td>ads#update</td>
<td>actualizar un anuncio específico para una revista específica</td>
</tr>
<tr>
<td>DELETE</td>
<td>/magazines/:magazine_id/ads/:id</td>
<td>ads#destroy</td>
<td>eliminar un anuncio específico para una revista específica</td>
</tr>
</tbody></table>
<p>Esto también creará helpers de ruta como <code>magazine_ads_url</code> y <code>edit_magazine_ad_path</code>. Estos helpers toman una instancia de Magazine como el primer parámetro (<code>magazine_ads_url(@magazine)</code>).</p><h4 id="límites-de-anidación"><a class="anchorlink" href="#límites-de-anidación"><span>2.7.1</span> Límites de Anidación</a></h4><p>Puedes anidar recursos dentro de otros recursos anidados si lo deseas. Por ejemplo:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:publishers</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:magazines</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:photos</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :publishers do
resources :magazines do
resources :photos
end
end
">Copy</button>
</div>
<p>Los recursos anidados profundamente rápidamente se vuelven engorrosos. En este caso, por ejemplo, la aplicación reconocería rutas como:</p><div class="interstitial code">
<pre><code class="highlight plaintext">/publishers/1/magazines/2/photos/3
</code></pre>
<button class="clipboard-button" data-clipboard-text="/publishers/1/magazines/2/photos/3
">Copy</button>
</div>
<p>El helper de ruta correspondiente sería <code>publisher_magazine_photo_url</code>, requiriendo que especifiques objetos en los tres niveles. De hecho, esta situación es lo suficientemente confusa como para que un <a href="http://weblog.jamisbuck.org/2007/2/5/nesting-resources">artículo popular de Jamis Buck</a> proponga una regla empírica para un buen diseño en Rails:</p><p>CONSEJO: Los recursos nunca deben anidarse más de 1 nivel de profundidad.</p><h4 id="anidación-superficial"><a class="anchorlink" href="#anidación-superficial"><span>2.7.2</span> Anidación Superficial</a></h4><p>Una forma de evitar la anidación profunda (como se recomienda arriba) es generar las acciones de colección bajo el ámbito del padre, para obtener una idea de la jerarquía, pero no anidar las acciones de miembro. En otras palabras, construir rutas solo con la cantidad mínima de información para identificar de manera única el recurso, así:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:articles</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:comments</span><span class="p">,</span> <span class="ss">only: </span><span class="p">[</span><span class="ss">:index</span><span class="p">,</span> <span class="ss">:new</span><span class="p">,</span> <span class="ss">:create</span><span class="p">]</span>
<span class="k">end</span>
<span class="n">resources</span> <span class="ss">:comments</span><span class="p">,</span> <span class="ss">only: </span><span class="p">[</span><span class="ss">:show</span><span class="p">,</span> <span class="ss">:edit</span><span class="p">,</span> <span class="ss">:update</span><span class="p">,</span> <span class="ss">:destroy</span><span class="p">]</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :articles do
resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]
">Copy</button>
</div>
<p>Esta idea encuentra un equilibrio entre rutas descriptivas y anidación profunda. Existe una sintaxis abreviada para lograr precisamente eso, a través de la opción <code>:shallow</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:articles</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:comments</span><span class="p">,</span> <span class="ss">shallow: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :articles do
resources :comments, shallow: true
end
">Copy</button>
</div>
<p>Esto generará exactamente las mismas rutas que el primer ejemplo. También puedes especificar la opción <code>:shallow</code> en el recurso padre, en cuyo caso todos los recursos anidados serán superficiales:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">resources</span> <span class="ss">:articles</span><span class="p">,</span> <span class="ss">shallow: </span><span class="kp">true</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:comments</span>
<span class="n">resources</span> <span class="ss">:quotes</span>
<span class="n">resources</span> <span class="ss">:drafts</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="resources :articles, shallow: true do
resources :comments
resources :quotes
resources :drafts
end
">Copy</button>
</div>
<p>El recurso articles aquí tendrá las siguientes rutas generadas para él:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Helper de Ruta Nombrada</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/articles/:article_id/comments(.:format)</td>
<td>comments#index</td>
<td>article_comments_path</td>
</tr>
<tr>
<td>POST</td>
<td>/articles/:article_id/comments(.:format)</td>
<td>comments#create</td>
<td>article_comments_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:article_id/comments/new(.:format)</td>
<td>comments#new</td>
<td>new_article_comment_path</td>
</tr>
<tr>
<td>GET</td>
<td>/comments/:id/edit(.:format)</td>
<td>comments#edit</td>
<td>edit_comment_path</td>
</tr>
<tr>
<td>GET</td>
<td>/comments/:id(.:format)</td>
<td>comments#show</td>
<td>comment_path</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/comments/:id(.:format)</td>
<td>comments#update</td>
<td>comment_path</td>
</tr>
<tr>
<td>DELETE</td>
<td>/comments/:id(.:format)</td>
<td>comments#destroy</td>
<td>comment_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:article_id/quotes(.:format)</td>
<td>quotes#index</td>
<td>article_quotes_path</td>
</tr>
<tr>
<td>POST</td>
<td>/articles/:article_id/quotes(.:format)</td>
<td>quotes#create</td>
<td>article_quotes_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:article_id/quotes/new(.:format)</td>
<td>quotes#new</td>
<td>new_article_quote_path</td>
</tr>
<tr>
<td>GET</td>
<td>/quotes/:id/edit(.:format)</td>
<td>quotes#edit</td>
<td>edit_quote_path</td>
</tr>
<tr>
<td>GET</td>
<td>/quotes/:id(.:format)</td>
<td>quotes#show</td>
<td>quote_path</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/quotes/:id(.:format)</td>
<td>quotes#update</td>
<td>quote_path</td>
</tr>
<tr>
<td>DELETE</td>
<td>/quotes/:id(.:format)</td>
<td>quotes#destroy</td>
<td>quote_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:article_id/drafts(.:format)</td>
<td>drafts#index</td>
<td>article_drafts_path</td>
</tr>
<tr>
<td>POST</td>
<td>/articles/:article_id/drafts(.:format)</td>
<td>drafts#create</td>
<td>article_drafts_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:article_id/drafts/new(.:format)</td>
<td>drafts#new</td>
<td>new_article_draft_path</td>
</tr>
<tr>
<td>GET</td>
<td>/drafts/:id/edit(.:format)</td>
<td>drafts#edit</td>
<td>edit_draft_path</td>
</tr>
<tr>
<td>GET</td>
<td>/drafts/:id(.:format)</td>
<td>drafts#show</td>
<td>draft_path</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/drafts/:id(.:format)</td>
<td>drafts#update</td>
<td>draft_path</td>
</tr>
<tr>
<td>DELETE</td>
<td>/drafts/:id(.:format)</td>
<td>drafts#destroy</td>
<td>draft_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles(.:format)</td>
<td>articles#index</td>
<td>articles_path</td>
</tr>
<tr>
<td>POST</td>
<td>/articles(.:format)</td>
<td>articles#create</td>
<td>articles_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/new(.:format)</td>
<td>articles#new</td>
<td>new_article_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:id/edit(.:format)</td>
<td>articles#edit</td>
<td>edit_article_path</td>
</tr>
<tr>
<td>GET</td>
<td>/articles/:id(.:format)</td>
<td>articles#show</td>
<td>article_path</td>
</tr>
<tr>
<td>PATCH/PUT</td>
<td>/articles/:id(.:format)</td>
<td>articles#update</td>
<td>article_path</td>
</tr>
<tr>
<td>DELETE</td>
<td>/articles/:id(.:format)</td>
<td>articles#destroy</td>
<td>article_path</td>
</tr>
</tbody></table>
<p>El método <a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-shallow"><code>shallow</code></a> del DSL crea un ámbito dentro del cual cada anidación es superficial. Esto genera las mismas rutas que el ejemplo anterior:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">shallow</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:articles</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:comments</span>
<span class="n">resources</span> <span class="ss">:quotes</span>
<span class="n">resources</span> <span class="ss">:drafts</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="shallow do
resources :articles do
resources :comments
resources :quotes
resources :drafts
end
end
">Copy</button>
</div>
<p>Existen dos opciones para <code>scope</code> para personalizar las rutas superficiales. <code>:shallow_path</code> prefija las rutas de miembro con el parámetro especificado:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">scope</span> <span class="ss">shallow_path: </span><span class="s2">"sekret"</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:articles</span> <span class="k">do</span>
<span class="n">resources</span> <span class="ss">:comments</span><span class="p">,</span> <span class="ss">shallow: </span><span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="scope shallow_path: "sekret" do
resources :articles do
resources :comments, shallow: true
end
end
">Copy</button>
</div>
<p>El recurso comments aquí tendrá las siguientes rutas generadas para él:</p>
<table><thead>
<tr>
<th>Verbo HTTP</th>
<th>Ruta</th>
<th>Controlador#Acción</th>
<th>Helper de Ruta Nombrada</th>
</tr>
</thead><tbody>
<tr>
<td>GET</td>
<td>/articles/:article_id/comments(.:format)</td>
<td>comments#index</td>
<td>article_comments_path</td>