-
Notifications
You must be signed in to change notification settings - Fork 0
/
active_record_validations.html
1695 lines (1622 loc) · 165 KB
/
active_record_validations.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>Validaciones de Active Record — 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="Validaciones de Active Record — Ruby on Rails Guides" />
<meta name="description" content="Validaciones de Active RecordEsta guía te enseña cómo validar el estado de los objetos antes de que ingresen a la base de datos utilizando la funcionalidad de validaciones de Active Record.Después de leer esta guía, sabrás: Cómo usar los ayudantes de validación integrados de Active Record. Cómo crear tus propios métodos de validación personalizados. Cómo trabajar con los mensajes de error generados por el proceso de validación." />
<meta property="og:description" content="Validaciones de Active RecordEsta guía te enseña cómo validar el estado de los objetos antes de que ingresen a la base de datos utilizando la funcionalidad de validaciones de Active Record.Después de leer esta guía, sabrás: Cómo usar los ayudantes de validación integrados de Active Record. Cómo crear tus propios métodos de validación personalizados. Cómo trabajar con los mensajes de error generados por el proceso de validación." />
<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:wght@100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@100..900&family=Noto+Sans+Arabic:wght@100..900&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">
<h1>Validaciones de Active Record</h1><p>Esta guía te enseña cómo validar el estado de los objetos antes de que ingresen a la base de datos utilizando la funcionalidad de validaciones de Active Record.</p><p>Después de leer esta guía, sabrás:</p>
<ul>
<li>Cómo usar los ayudantes de validación integrados de Active Record.</li>
<li>Cómo crear tus propios métodos de validación personalizados.</li>
<li>Cómo trabajar con los mensajes de error generados por el proceso de validación.</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="#visión-general-de-las-validaciones">Visión General de las Validaciones</a>
<ul>
<li><a href="#¿por-qué-usar-validaciones-questionmark">¿Por qué Usar Validaciones?</a></li>
<li><a href="#¿cuándo-ocurre-la-validación-questionmark">¿Cuándo Ocurre la Validación?</a></li>
<li><a href="#omitiendo-validaciones">Omitiendo Validaciones</a></li>
<li><a href="#valid-questionmark-e-invalid-questionmark"><code>valid?</code> e <code>invalid?</code></a></li>
<li><a href="#visión-general-de-las-validaciones-errors"><code>errors[]</code></a></li>
</ul></li>
<li><a href="#ayudantes-de-validación">Ayudantes de Validación</a>
<ul>
<li><a href="#acceptance"><code>acceptance</code></a></li>
<li><a href="#confirmation"><code>confirmation</code></a></li>
<li><a href="#comparison"><code>comparison</code></a></li>
<li><a href="#format"><code>format</code></a></li>
<li><a href="#inclusion"><code>inclusion</code></a></li>
<li><a href="#exclusion"><code>exclusion</code></a></li>
<li><a href="#length"><code>length</code></a></li>
<li><a href="#numericality"><code>numericality</code></a></li>
<li><a href="#presence"><code>presence</code></a></li>
<li><a href="#absence"><code>absence</code></a></li>
<li><a href="#uniqueness"><code>uniqueness</code></a></li>
<li><a href="#validates-associated"><code>validates_associated</code></a></li>
<li><a href="#validates-each"><code>validates_each</code></a></li>
<li><a href="#validates-with"><code>validates_with</code></a></li>
</ul></li>
<li><a href="#opciones-comunes-de-validación">Opciones Comunes de Validación</a>
<ul>
<li><a href="#allow-nil"><code>:allow_nil</code></a></li>
<li><a href="#allow-blank"><code>:allow_blank</code></a></li>
<li><a href="#message"><code>:message</code></a></li>
<li><a href="#on"><code>:on</code></a></li>
</ul></li>
<li><a href="#validaciones-estrictas">Validaciones Estrictas</a></li>
<li><a href="#validación-condicional">Validación Condicional</a>
<ul>
<li><a href="#usando-un-símbolo-con-if-y-unless">Usando un Símbolo con <code>:if</code> y <code>:unless</code></a></li>
<li><a href="#usando-un-proc-con-if-y-unless">Usando un Proc con <code>:if</code> y <code>:unless</code></a></li>
<li><a href="#agrupando-validaciones-condicionales">Agrupando Validaciones Condicionales</a></li>
<li><a href="#combinando-condiciones-de-validación">Combinando Condiciones de Validación</a></li>
</ul></li>
<li><a href="#realizando-validaciones-personalizadas">Realizando Validaciones Personalizadas</a>
<ul>
<li><a href="#validadores-personalizados">Validadores Personalizados</a></li>
<li><a href="#métodos-personalizados">Métodos Personalizados</a></li>
<li><a href="#listando-validadores">Listando Validadores</a></li>
</ul></li>
<li><a href="#trabajando-con-errores-de-validación">Trabajando con Errores de Validación</a>
<ul>
<li><a href="#trabajando-con-errores-de-validación-errors"><code>errors</code></a></li>
<li><a href="#errors"><code>errors[]</code></a></li>
<li><a href="#errors-where-y-objeto-de-error"><code>errors.where</code> y Objeto de Error</a></li>
<li><a href="#errors-add"><code>errors.add</code></a></li>
<li><a href="#errors-base"><code>errors[:base]</code></a></li>
<li><a href="#errors-size"><code>errors.size</code></a></li>
<li><a href="#errors-clear"><code>errors.clear</code></a></li>
</ul></li>
<li><a href="#mostrando-errores-de-validación-en-vistas">Mostrando Errores de Validación en Vistas</a></li>
</ol>
</nav>
<hr>
</div>
</section>
<main id="container">
<div class="wrapper">
<div id="mainCol">
<h2 id="visión-general-de-las-validaciones"><a class="anchorlink" href="#visión-general-de-las-validaciones"><span>1</span> Visión General de las Validaciones</a></h2><p>Aquí hay un ejemplo de una validación muy simple:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, presence: true
end
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">name: </span><span class="s2">"John Doe"</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">true</span>
<span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">name: </span><span class="kp">nil</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">false</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Person.create(name: "John Doe").valid?
Person.create(name: nil).valid?
">Copy</button>
</div>
<p>Como puedes ver, nuestra validación nos informa que nuestro <code>Person</code> no es válido sin un atributo <code>name</code>. El segundo <code>Person</code> no se guardará en la base de datos.</p><p>Antes de profundizar en más detalles, hablemos de cómo las validaciones encajan en el panorama general de tu aplicación.</p><h3 id="¿por-qué-usar-validaciones-questionmark"><a class="anchorlink" href="#¿por-qué-usar-validaciones-questionmark"><span>1.1</span> ¿Por qué Usar Validaciones?</a></h3><p>Las validaciones se utilizan para asegurar que solo datos válidos se guarden en tu base de datos. Por ejemplo, puede ser importante para tu aplicación asegurarse de que cada usuario proporcione una dirección de correo electrónico y una dirección postal válidas. Las validaciones a nivel de modelo son la mejor manera de asegurar que solo datos válidos se guarden en tu base de datos. Son independientes de la base de datos, no pueden ser eludidas por los usuarios finales, y son convenientes para probar y mantener. Rails proporciona ayudantes integrados para necesidades comunes y te permite crear tus propios métodos de validación también.</p><p>Hay varias otras maneras de validar datos antes de que se guarden en tu base de datos, incluyendo restricciones nativas de la base de datos, validaciones del lado del cliente y validaciones a nivel de controlador. Aquí hay un resumen de los pros y contras:</p>
<ul>
<li>Las restricciones de la base de datos y/o los procedimientos almacenados hacen que los mecanismos de validación dependan de la base de datos y pueden hacer que las pruebas y el mantenimiento sean más difíciles. Sin embargo, si tu base de datos es utilizada por otras aplicaciones, puede ser una buena idea usar algunas restricciones a nivel de base de datos. Además, las validaciones a nivel de base de datos pueden manejar de manera segura algunas cosas (como la unicidad en tablas muy utilizadas) que pueden ser difíciles de implementar de otra manera.</li>
<li>Las validaciones del lado del cliente pueden ser útiles, pero generalmente son poco confiables si se usan solas. Si se implementan usando JavaScript, pueden ser eludidas si JavaScript está desactivado en el navegador del usuario. Sin embargo, si se combinan con otras técnicas, la validación del lado del cliente puede ser una manera conveniente de proporcionar retroalimentación inmediata a los usuarios mientras usan tu sitio.</li>
<li>Las validaciones a nivel de controlador pueden ser tentadoras de usar, pero a menudo se vuelven inmanejables y difíciles de probar y mantener. Siempre que sea posible, es una buena idea mantener tus controladores simples, ya que hará que tu aplicación sea un placer de trabajar a largo plazo.</li>
</ul>
<p>Elige estas opciones en ciertos casos específicos. Es la opinión del equipo de Rails que las validaciones a nivel de modelo son las más apropiadas en la mayoría de las circunstancias.</p><h3 id="¿cuándo-ocurre-la-validación-questionmark"><a class="anchorlink" href="#¿cuándo-ocurre-la-validación-questionmark"><span>1.2</span> ¿Cuándo Ocurre la Validación?</a></h3><p>Hay dos tipos de objetos Active Record: aquellos que corresponden a una fila dentro de tu base de datos y aquellos que no. Cuando creas un objeto nuevo, por ejemplo usando el método <code>new</code>, ese objeto aún no pertenece a la base de datos. Una vez que llamas a <code>save</code> sobre ese objeto, se guardará en la tabla de base de datos apropiada. Active Record utiliza el método de instancia <code>new_record?</code> para determinar si un objeto ya está en la base de datos o no. Considera la siguiente clase de Active Record:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
end
">Copy</button>
</div>
<p>Podemos ver cómo funciona observando algunos resultados de <code>bin/rails console</code>:</p><div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="nb">p</span> <span class="o">=</span> <span class="no">Person</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">name: </span><span class="s2">"John Doe"</span><span class="p">)</span>
<span class="p">=></span> <span class="kt">#<</span><span class="no">Person</span> <span class="ss">id: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">name: </span><span class="s2">"John Doe"</span><span class="p">,</span> <span class="ss">created_at: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">updated_at: </span><span class="kp">nil</span><span class="kt">></span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">new_record?</span>
<span class="p">=></span> <span class="kp">true</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">save</span>
<span class="p">=></span> <span class="kp">true</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">new_record?</span>
<span class="p">=></span> <span class="kp">false</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="p = Person.new(name: "John Doe")
p.new_record?
p.save
p.new_record?
">Copy</button>
</div>
<p>Crear y guardar un nuevo registro enviará una operación SQL <code>INSERT</code> a la base de datos. Actualizar un registro existente enviará una operación SQL <code>UPDATE</code> en su lugar. Las validaciones generalmente se ejecutan antes de que estos comandos se envíen a la base de datos. Si alguna validación falla, el objeto será marcado como no válido y Active Record no realizará la operación <code>INSERT</code> o <code>UPDATE</code>. Esto evita almacenar un objeto no válido en la base de datos. Puedes elegir que se ejecuten validaciones específicas cuando un objeto se crea, guarda o actualiza.</p><p>PRECAUCIÓN: Hay muchas maneras de cambiar el estado de un objeto en la base de datos. Algunos métodos activarán validaciones, pero otros no. Esto significa que es posible guardar un objeto en la base de datos en un estado no válido si no tienes cuidado.</p><p>Los siguientes métodos activan validaciones y guardarán el objeto en la base de datos solo si el objeto es válido:</p>
<ul>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create"><code>create</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create-21"><code>create!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save"><code>save</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save-21"><code>save!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update"><code>update</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update-21"><code>update!</code></a></li>
</ul>
<p>Las versiones con signo de exclamación (por ejemplo, <code>save!</code>) lanzan una excepción si el registro es inválido. Las versiones sin signo de exclamación no lo hacen: <code>save</code> y <code>update</code> devuelven <code>false</code>, y <code>create</code> devuelve el objeto.</p><h3 id="omitiendo-validaciones"><a class="anchorlink" href="#omitiendo-validaciones"><span>1.3</span> Omitiendo Validaciones</a></h3><p>Los siguientes métodos omiten validaciones y guardarán el objeto en la base de datos independientemente de su validez. Deben usarse con precaución. Consulta la documentación del método para obtener más información.</p>
<ul>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-decrement-21"><code>decrement!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/CounterCache/ClassMethods.html#method-i-decrement_counter"><code>decrement_counter</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-increment-21"><code>increment!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/CounterCache/ClassMethods.html#method-i-increment_counter"><code>increment_counter</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-insert"><code>insert</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-insert-21"><code>insert!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-insert_all"><code>insert_all</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-insert_all-21"><code>insert_all!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-toggle-21"><code>toggle!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-touch"><code>touch</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-touch_all"><code>touch_all</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-update_all"><code>update_all</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute"><code>update_attribute</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute-21"><code>update_attribute!</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column"><code>update_column</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_columns"><code>update_columns</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-update_counters"><code>update_counters</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-upsert"><code>upsert</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-upsert_all"><code>upsert_all</code></a></li>
</ul>
<p>Ten en cuenta que <code>save</code> también tiene la capacidad de omitir validaciones si se pasa <code>validate: false</code> como argumento. Esta técnica debe usarse con precaución.</p>
<ul>
<li><code>save(validate: false)</code></li>
</ul>
<h3 id="valid-questionmark-e-invalid-questionmark"><a class="anchorlink" href="#valid-questionmark-e-invalid-questionmark"><span>1.4</span> <code>valid?</code> e <code>invalid?</code></a></h3><p>Antes de guardar un objeto Active Record, Rails ejecuta tus validaciones. Si estas validaciones producen algún error, Rails no guarda el objeto.</p><p>También puedes ejecutar estas validaciones por tu cuenta. <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Validations.html#method-i-valid-3F"><code>valid?</code></a> activa tus validaciones y devuelve true si no se encontraron errores en el objeto, y false en caso contrario. Como viste arriba:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, presence: true
end
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">name: </span><span class="s2">"John Doe"</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">true</span>
<span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">name: </span><span class="kp">nil</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">false</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Person.create(name: "John Doe").valid?
Person.create(name: nil).valid?
">Copy</button>
</div>
<p>Después de que Active Record ha realizado las validaciones, cualquier falla puede ser accedida a través del método de instancia <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-errors"><code>errors</code></a>, que devuelve una colección de errores. Por definición, un objeto es válido si esta colección está vacía después de ejecutar las validaciones.</p><p>Ten en cuenta que un objeto instanciado con <code>new</code> no reportará errores incluso si es técnicamente inválido, porque las validaciones se ejecutan automáticamente solo cuando el objeto se guarda, como con los métodos <code>create</code> o <code>save</code>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, presence: true
end
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="nb">p</span> <span class="o">=</span> <span class="no">Person</span><span class="p">.</span><span class="nf">new</span>
<span class="p">=></span> <span class="kt">#<</span><span class="no">Person</span> <span class="ss">id: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">name: </span><span class="kp">nil</span><span class="kt">></span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">size</span>
<span class="p">=></span> <span class="mi">0</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">false</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">objects</span><span class="p">.</span><span class="nf">first</span><span class="p">.</span><span class="nf">full_message</span>
<span class="p">=></span> <span class="s2">"Name can't be blank"</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span> <span class="o">=</span> <span class="no">Person</span><span class="p">.</span><span class="nf">create</span>
<span class="p">=></span> <span class="kt">#<</span><span class="no">Person</span> <span class="ss">id: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">name: </span><span class="kp">nil</span><span class="kt">></span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">objects</span><span class="p">.</span><span class="nf">first</span><span class="p">.</span><span class="nf">full_message</span>
<span class="p">=></span> <span class="s2">"Name can't be blank"</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">save</span>
<span class="p">=></span> <span class="kp">false</span>
<span class="gp">irb></span><span class="w"> </span><span class="nb">p</span><span class="p">.</span><span class="nf">save!</span>
<span class="go">ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
</span><span class="err">
</span><span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">create!</span>
<span class="go">ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="p = Person.new
p.errors.size
p.valid?
p.errors.objects.first.full_message
p = Person.create
p.errors.objects.first.full_message
p.save
p.save!
Person.create!
">Copy</button>
</div>
<p><a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-invalid-3F"><code>invalid?</code></a> es la inversa de <code>valid?</code>. Activa tus validaciones, devolviendo true si se encontraron errores en el objeto, y false en caso contrario.</p><h3 id="visión-general-de-las-validaciones-errors"><a class="anchorlink" href="#visión-general-de-las-validaciones-errors"><span>1.5</span> <code>errors[]</code></a></h3><p>Para verificar si un atributo particular de un objeto es válido, puedes usar <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-5B-5D"><code>errors[:attribute]</code></a>. Devuelve un array de todos los mensajes de error para <code>:attribute</code>. Si no hay errores en el atributo especificado, se devuelve un array vacío.</p><p>Este método solo es útil <em>después</em> de que las validaciones se hayan ejecutado, porque solo inspecciona la colección de errores y no activa las validaciones por sí mismo. Es diferente del método <code>ActiveRecord::Base#invalid?</code> explicado anteriormente porque no verifica la validez del objeto en su conjunto. Solo comprueba si hay errores encontrados en un atributo individual del objeto.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, presence: true
end
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">errors</span><span class="p">[</span><span class="ss">:name</span><span class="p">].</span><span class="nf">any?</span>
<span class="p">=></span> <span class="kp">false</span>
<span class="gp">irb></span><span class="w"> </span><span class="no">Person</span><span class="p">.</span><span class="nf">create</span><span class="p">.</span><span class="nf">errors</span><span class="p">[</span><span class="ss">:name</span><span class="p">].</span><span class="nf">any?</span>
<span class="p">=></span> <span class="kp">true</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Person.new.errors[:name].any?
Person.create.errors[:name].any?
">Copy</button>
</div>
<p>Cubriremos los errores de validación en mayor profundidad en la sección <a href="#trabajando-con-errores-de-validación">Trabajando con Errores de Validación</a>.</p><h2 id="ayudantes-de-validación"><a class="anchorlink" href="#ayudantes-de-validación"><span>2</span> Ayudantes de Validación</a></h2><p>Active Record ofrece muchos ayudantes de validación predefinidos que puedes usar directamente dentro de tus definiciones de clase. Estos ayudantes proporcionan reglas de validación comunes. Cada vez que una validación falla, se agrega un error a la colección <code>errors</code> del objeto, y esto se asocia con el atributo que se está validando.</p><p>Cada ayudante acepta un número arbitrario de nombres de atributos, por lo que con una sola línea de código puedes agregar el mismo tipo de validación a varios atributos.</p><p>Todos ellos aceptan las opciones <code>:on</code> y <code>:message</code>, que definen cuándo se debe ejecutar la validación y qué mensaje se debe agregar a la colección <code>errors</code> si falla, respectivamente. La opción <code>:on</code> toma uno de los valores <code>:create</code> o <code>:update</code>. Hay un mensaje de error predeterminado para cada uno de los ayudantes de validación. Estos mensajes se utilizan cuando no se especifica la opción <code>:message</code>. Echemos un vistazo a cada uno de los ayudantes disponibles.</p><div class="interstitial info"><p>Para ver una lista de los ayudantes predeterminados disponibles, echa un vistazo a <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html"><code>ActiveModel::Validations::HelperMethods</code></a>.</p></div><h3 id="acceptance"><a class="anchorlink" href="#acceptance"><span>2.1</span> <code>acceptance</code></a></h3><p>Este método valida que un checkbox en la interfaz de usuario fue marcado cuando se envió un formulario. Esto se utiliza típicamente cuando el usuario necesita aceptar los términos de servicio de tu aplicación, confirmar que se ha leído un texto o cualquier concepto similar.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:terms_of_service</span><span class="p">,</span> <span class="ss">acceptance: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :terms_of_service, acceptance: true
end
">Copy</button>
</div>
<p>Esta verificación se realiza solo si <code>terms_of_service</code> no es <code>nil</code>. El mensaje de error predeterminado para este ayudante es <em>"must be accepted"</em>. También puedes pasar un mensaje personalizado a través de la opción <code>message</code>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:terms_of_service</span><span class="p">,</span> <span class="ss">acceptance: </span><span class="p">{</span> <span class="ss">message: </span><span class="s1">'must be abided'</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :terms_of_service, acceptance: { message: 'must be abided' }
end
">Copy</button>
</div>
<p>También puede recibir una opción <code>:accept</code>, que determina los valores permitidos que se considerarán como aceptables. Por defecto es <code>['1', true]</code> y se puede cambiar fácilmente.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:terms_of_service</span><span class="p">,</span> <span class="ss">acceptance: </span><span class="p">{</span> <span class="ss">accept: </span><span class="s1">'yes'</span> <span class="p">}</span>
<span class="n">validates</span> <span class="ss">:eula</span><span class="p">,</span> <span class="ss">acceptance: </span><span class="p">{</span> <span class="ss">accept: </span><span class="p">[</span><span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">'accepted'</span><span class="p">]</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :terms_of_service, acceptance: { accept: 'yes' }
validates :eula, acceptance: { accept: ['TRUE', 'accepted'] }
end
">Copy</button>
</div>
<p>Esta validación es muy específica para aplicaciones web y esta 'aceptación' no necesita registrarse en ningún lugar de tu base de datos. Si no tienes un campo para ello, el ayudante creará un atributo virtual. Si el campo existe en tu base de datos, la opción <code>accept</code> debe establecerse en o incluir <code>true</code> o de lo contrario la validación no se ejecutará.</p><h3 id="confirmation"><a class="anchorlink" href="#confirmation"><span>2.2</span> <code>confirmation</code></a></h3><p>Debes usar este ayudante cuando tengas dos campos de texto que deben recibir exactamente el mismo contenido. Por ejemplo, es posible que desees confirmar una dirección de correo electrónico o una contraseña. Esta validación crea un atributo virtual cuyo nombre es el nombre del campo que debe confirmarse con "_confirmation" añadido.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">confirmation: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :email, confirmation: true
end
">Copy</button>
</div>
<p>En tu plantilla de vista podrías usar algo como</p><div class="interstitial code">
<pre><code class="highlight erb"><span class="cp"><%=</span> <span class="n">text_field</span> <span class="ss">:person</span><span class="p">,</span> <span class="ss">:email</span> <span class="cp">%></span>
<span class="cp"><%=</span> <span class="n">text_field</span> <span class="ss">:person</span><span class="p">,</span> <span class="ss">:email_confirmation</span> <span class="cp">%></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<%= text_field :person, :email %>
<%= text_field :person, :email_confirmation %>
">Copy</button>
</div>
<p>NOTA: Esta verificación se realiza solo si <code>email_confirmation</code> no es <code>nil</code>. Para requerir confirmación, asegúrate de agregar una verificación de presencia para el atributo de confirmación (veremos <code>presence</code> <a href="#presence">más adelante</a> en esta guía):</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">confirmation: </span><span class="kp">true</span>
<span class="n">validates</span> <span class="ss">:email_confirmation</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :email, confirmation: true
validates :email_confirmation, presence: true
end
">Copy</button>
</div>
<p>También hay una opción <code>:case_sensitive</code> que puedes usar para definir si la restricción de confirmación será sensible a mayúsculas o no. Esta opción por defecto es true.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">confirmation: </span><span class="p">{</span> <span class="ss">case_sensitive: </span><span class="kp">false</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :email, confirmation: { case_sensitive: false }
end
">Copy</button>
</div>
<p>El mensaje de error predeterminado para este ayudante es <em>"doesn't match confirmation"</em>. También puedes pasar un mensaje personalizado a través de la opción <code>message</code>.</p><p>Generalmente, cuando usas este validador, querrás combinarlo con la opción <code>:if</code> para validar el campo "_confirmation" solo cuando el campo inicial haya cambiado y <strong>no</strong> cada vez que guardes el registro. Más sobre <a href="#validación-condicional">validaciones condicionales</a> más adelante.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">confirmation: </span><span class="kp">true</span>
<span class="n">validates</span> <span class="ss">:email_confirmation</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">if: :email_changed?</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :email, confirmation: true
validates :email_confirmation, presence: true, if: :email_changed?
end
">Copy</button>
</div>
<h3 id="comparison"><a class="anchorlink" href="#comparison"><span>2.3</span> <code>comparison</code></a></h3><p>Esta verificación validará una comparación entre dos valores comparables.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Promotion</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:end_date</span><span class="p">,</span> <span class="ss">comparison: </span><span class="p">{</span> <span class="ss">greater_than: :start_date</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Promotion < ApplicationRecord
validates :end_date, comparison: { greater_than: :start_date }
end
">Copy</button>
</div>
<p>El mensaje de error predeterminado para este ayudante es <em>"failed comparison"</em>. También puedes pasar un mensaje personalizado a través de la opción <code>message</code>.</p><p>Estas opciones son todas compatibles:</p>
<ul>
<li><code>:greater_than</code> - Especifica que el valor debe ser mayor que el valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be greater than %{count}"</em>.</li>
<li><code>:greater_than_or_equal_to</code> - Especifica que el valor debe ser mayor o igual al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be greater than or equal to %{count}"</em>.</li>
<li><code>:equal_to</code> - Especifica que el valor debe ser igual al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be equal to %{count}"</em>.</li>
<li><code>:less_than</code> - Especifica que el valor debe ser menor que el valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be less than %{count}"</em>.</li>
<li><code>:less_than_or_equal_to</code> - Especifica que el valor debe ser menor o igual al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be less than or equal to %{count}"</em>.</li>
<li><code>:other_than</code> - Especifica que el valor debe ser diferente al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be other than %{count}"</em>.</li>
</ul>
<p>NOTA: El validador requiere que se proporcione una opción de comparación. Cada opción acepta un valor, proc o símbolo. Cualquier clase que incluya Comparable puede ser comparada.</p><h3 id="format"><a class="anchorlink" href="#format"><span>2.4</span> <code>format</code></a></h3><p>Este ayudante valida los valores de los atributos probando si coinciden con una expresión regular dada, que se especifica usando la opción <code>:with</code>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Product</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:legacy_code</span><span class="p">,</span> <span class="ss">format: </span><span class="p">{</span> <span class="ss">with: </span><span class="sr">/\A[a-zA-Z]+\z/</span><span class="p">,</span>
<span class="ss">message: </span><span class="s2">"only allows letters"</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Product < ApplicationRecord
validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
message: "only allows letters" }
end
">Copy</button>
</div>
<p>Inversamente, al usar la opción <code>:without</code> en su lugar, puedes requerir que el atributo especificado <em>no</em> coincida con la expresión regular.</p><p>En cualquier caso, la opción <code>:with</code> o <code>:without</code> proporcionada debe ser una expresión regular o un proc o lambda que devuelva una.</p><p>El mensaje de error predeterminado es <em>"is invalid"</em>.</p><p>ADVERTENCIA. usa <code>\A</code> y <code>\z</code> para coincidir con el inicio y el final de la cadena, <code>^</code> y <code>$</code> coinciden con el inicio/final de una línea. Debido al uso frecuente incorrecto de <code>^</code> y <code>$</code>, necesitas pasar la opción <code>multiline: true</code> en caso de que uses alguno de estos dos anclajes en la expresión regular proporcionada. En la mayoría de los casos, deberías estar usando <code>\A</code> y <code>\z</code>.</p><h3 id="inclusion"><a class="anchorlink" href="#inclusion"><span>2.5</span> <code>inclusion</code></a></h3><p>Este ayudante valida que los valores de los atributos estén incluidos en un conjunto dado. De hecho, este conjunto puede ser cualquier objeto enumerable.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Coffee</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:size</span><span class="p">,</span> <span class="ss">inclusion: </span><span class="p">{</span> <span class="ss">in: </span><span class="sx">%w(small medium large)</span><span class="p">,</span>
<span class="ss">message: </span><span class="s2">"%{value} is not a valid size"</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }
end
">Copy</button>
</div>
<p>El ayudante <code>inclusion</code> tiene una opción <code>:in</code> que recibe el conjunto de valores que serán aceptados. La opción <code>:in</code> tiene un alias llamado <code>:within</code> que puedes usar para el mismo propósito, si lo deseas. El ejemplo anterior usa la opción <code>:message</code> para mostrar cómo puedes incluir el valor del atributo. Para ver todas las opciones, consulta la <a href="#message">documentación del mensaje</a>.</p><p>El mensaje de error predeterminado para este ayudante es <em>"is not included in the list"</em>.</p><h3 id="exclusion"><a class="anchorlink" href="#exclusion"><span>2.6</span> <code>exclusion</code></a></h3><p>El opuesto de <code>inclusion</code> es... ¡<code>exclusion</code>!</p><p>Este ayudante valida que los valores de los atributos no estén incluidos en un conjunto dado. De hecho, este conjunto puede ser cualquier objeto enumerable.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Account</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:subdomain</span><span class="p">,</span> <span class="ss">exclusion: </span><span class="p">{</span> <span class="ss">in: </span><span class="sx">%w(www us ca jp)</span><span class="p">,</span>
<span class="ss">message: </span><span class="s2">"%{value} is reserved."</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Account < ApplicationRecord
validates :subdomain, exclusion: { in: %w(www us ca jp),
message: "%{value} is reserved." }
end
">Copy</button>
</div>
<p>El ayudante <code>exclusion</code> tiene una opción <code>:in</code> que recibe el conjunto de valores que no serán aceptados para los atributos validados. La opción <code>:in</code> tiene un alias llamado <code>:within</code> que puedes usar para el mismo propósito, si lo deseas. Este ejemplo usa la opción <code>:message</code> para mostrar cómo puedes incluir el valor del atributo. Para ver todas las opciones del argumento del mensaje, consulta la <a href="#message">documentación del mensaje</a>.</p><p>El mensaje de error predeterminado es <em>"is reserved"</em>.</p><p>Alternativamente a un enumerable tradicional (como un Array), puedes proporcionar un proc, lambda o símbolo que devuelva un enumerable. Si el enumerable es un rango numérico, de tiempo o de fecha y hora, la prueba se realiza con <code>Range#cover?</code>, de lo contrario con <code>include?</code>. Cuando se usa un proc o lambda, se pasa la instancia bajo validación como argumento.</p><h3 id="length"><a class="anchorlink" href="#length"><span>2.7</span> <code>length</code></a></h3><p>Este ayudante valida la longitud de los valores de los atributos. Proporciona una variedad de opciones, por lo que puedes especificar restricciones de longitud de diferentes maneras:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">length: </span><span class="p">{</span> <span class="ss">minimum: </span><span class="mi">2</span> <span class="p">}</span>
<span class="n">validates</span> <span class="ss">:bio</span><span class="p">,</span> <span class="ss">length: </span><span class="p">{</span> <span class="ss">maximum: </span><span class="mi">500</span> <span class="p">}</span>
<span class="n">validates</span> <span class="ss">:password</span><span class="p">,</span> <span class="ss">length: </span><span class="p">{</span> <span class="ss">in: </span><span class="mi">6</span><span class="o">..</span><span class="mi">20</span> <span class="p">}</span>
<span class="n">validates</span> <span class="ss">:registration_number</span><span class="p">,</span> <span class="ss">length: </span><span class="p">{</span> <span class="ss">is: </span><span class="mi">6</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, length: { minimum: 2 }
validates :bio, length: { maximum: 500 }
validates :password, length: { in: 6..20 }
validates :registration_number, length: { is: 6 }
end
">Copy</button>
</div>
<p>Las posibles opciones de restricción de longitud son:</p>
<ul>
<li><code>:minimum</code> - El atributo no puede tener menos de la longitud especificada.</li>
<li><code>:maximum</code> - El atributo no puede tener más de la longitud especificada.</li>
<li><code>:in</code> (o <code>:within</code>) - La longitud del atributo debe estar incluida en un intervalo dado. El valor para esta opción debe ser un rango.</li>
<li><code>:is</code> - La longitud del atributo debe ser igual al valor dado.</li>
</ul>
<p>Los mensajes de error predeterminados dependen del tipo de validación de longitud que se esté realizando. Puedes personalizar estos mensajes usando las opciones <code>:wrong_length</code>, <code>:too_long</code> y <code>:too_short</code>, y <code>%{count}</code> como un marcador de posición para el número correspondiente a la restricción de longitud que se está utilizando. Aún puedes usar la opción <code>:message</code> para especificar un mensaje de error.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:bio</span><span class="p">,</span> <span class="ss">length: </span><span class="p">{</span> <span class="ss">maximum: </span><span class="mi">1000</span><span class="p">,</span>
<span class="ss">too_long: </span><span class="s2">"%{count} characters is the maximum allowed"</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :bio, length: { maximum: 1000,
too_long: "%{count} characters is the maximum allowed" }
end
">Copy</button>
</div>
<p>Ten en cuenta que los mensajes de error predeterminados son plurales (por ejemplo, "is too short (minimum is %{count} characters)"). Por esta razón, cuando <code>:minimum</code> es 1, deberías proporcionar un mensaje personalizado o usar <code>presence: true</code> en su lugar. Cuando <code>:in</code> o <code>:within</code> tienen un límite inferior de 1, deberías proporcionar un mensaje personalizado o llamar a <code>presence</code> antes de <code>length</code>.</p><p>NOTA: Solo se puede usar una opción de restricción a la vez, aparte de las opciones <code>:minimum</code> y <code>:maximum</code>, que se pueden combinar juntas.</p><h3 id="numericality"><a class="anchorlink" href="#numericality"><span>2.8</span> <code>numericality</code></a></h3><p>Este ayudante valida que tus atributos tengan solo valores numéricos. Por defecto, coincidirá con un signo opcional seguido de un número entero o decimal.</p><p>Para especificar que solo se permiten números enteros, establece <code>:only_integer</code> en true. Luego usará la siguiente expresión regular para validar el valor del atributo.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="sr">/\A[+-]?\d+\z/</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="/\A[+-]?\d+\z/
">Copy</button>
</div>
<p>De lo contrario, intentará convertir el valor a un número usando <code>Float</code>. Los <code>Float</code> se convierten a <code>BigDecimal</code> usando el valor de precisión de la columna o un máximo de 15 dígitos.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Player</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:points</span><span class="p">,</span> <span class="ss">numericality: </span><span class="kp">true</span>
<span class="n">validates</span> <span class="ss">:games_played</span><span class="p">,</span> <span class="ss">numericality: </span><span class="p">{</span> <span class="ss">only_integer: </span><span class="kp">true</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Player < ApplicationRecord
validates :points, numericality: true
validates :games_played, numericality: { only_integer: true }
end
">Copy</button>
</div>
<p>El mensaje de error predeterminado para <code>:only_integer</code> es <em>"must be an integer"</em>.</p><p>Además de <code>:only_integer</code>, este ayudante también acepta la opción <code>:only_numeric</code> que especifica que el valor debe ser una instancia de <code>Numeric</code> e intenta analizar el valor si es una <code>String</code>.</p><p>NOTA: Por defecto, <code>numericality</code> no permite valores <code>nil</code>. Puedes usar la opción <code>allow_nil: true</code> para permitirlo. Ten en cuenta que para las columnas <code>Integer</code> y <code>Float</code>, las cadenas vacías se convierten en <code>nil</code>.</p><p>El mensaje de error predeterminado cuando no se especifican opciones es <em>"is not a number"</em>.</p><p>También hay muchas opciones que se pueden usar para agregar restricciones a los valores aceptables:</p>
<ul>
<li><code>:greater_than</code> - Especifica que el valor debe ser mayor que el valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be greater than %{count}"</em>.</li>
<li><code>:greater_than_or_equal_to</code> - Especifica que el valor debe ser mayor o igual al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be greater than or equal to %{count}"</em>.</li>
<li><code>:equal_to</code> - Especifica que el valor debe ser igual al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be equal to %{count}"</em>.</li>
<li><code>:less_than</code> - Especifica que el valor debe ser menor que el valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be less than %{count}"</em>.</li>
<li><code>:less_than_or_equal_to</code> - Especifica que el valor debe ser menor o igual al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be less than or equal to %{count}"</em>.</li>
<li><code>:other_than</code> - Especifica que el valor debe ser diferente al valor suministrado. El mensaje de error predeterminado para esta opción es <em>"must be other than %{count}"</em>.</li>
<li><code>:in</code> - Especifica que el valor debe estar en el rango suministrado. El mensaje de error predeterminado para esta opción es <em>"must be in %{count}"</em>.</li>
<li><code>:odd</code> - Especifica que el valor debe ser un número impar. El mensaje de error predeterminado para esta opción es <em>"must be odd"</em>.</li>
<li><code>:even</code> - Especifica que el valor debe ser un número par. El mensaje de error predeterminado para esta opción es <em>"must be even"</em>.</li>
</ul>
<h3 id="presence"><a class="anchorlink" href="#presence"><span>2.9</span> <code>presence</code></a></h3><p>Este ayudante valida que los atributos especificados no estén vacíos. Utiliza el método <a href="https://edgeapi.rubyonrails.org/classes/Object.html#method-i-blank-3F"><code>Object#blank?</code></a> para comprobar si el valor es <code>nil</code> o una cadena vacía, es decir, una cadena que esté vacía o que consista solo en espacios en blanco.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:login</span><span class="p">,</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, :login, :email, presence: true
end
">Copy</button>
</div>
<p>Si deseas asegurarte de que una asociación esté presente, necesitarás verificar si el objeto asociado en sí está presente, y no solo la clave foránea utilizada para mapear la asociación. De esta manera, no solo se verifica que la clave foránea no esté vacía, sino también que el objeto referenciado exista.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Supplier</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">has_one</span> <span class="ss">:account</span>
<span class="n">validates</span> <span class="ss">:account</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Supplier < ApplicationRecord
has_one :account
validates :account, presence: true
end
">Copy</button>
</div>
<p>Para validar registros asociados cuya presencia es requerida, debes especificar la opción <code>:inverse_of</code> para la asociación:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Order</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">has_many</span> <span class="ss">:line_items</span><span class="p">,</span> <span class="ss">inverse_of: :order</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Order < ApplicationRecord
has_many :line_items, inverse_of: :order
end
">Copy</button>
</div>
<p>NOTA: Si deseas asegurarte de que la asociación esté tanto presente como válida, también necesitas usar <code>validates_associated</code>. Más sobre eso <a href="#validates-associated">abajo</a>.</p><p>Si validas la presencia de un objeto asociado a través de una relación <code>has_one</code> o <code>has_many</code>, verificará que el objeto no sea <code>blank?</code> ni <code>marked_for_destruction?</code>.</p><p>Dado que <code>false.blank?</code> es true, si deseas validar la presencia de un campo booleano, debes usar una de las siguientes validaciones:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="c1"># El valor _debe_ ser true o false</span>
<span class="n">validates</span> <span class="ss">:boolean_field_name</span><span class="p">,</span> <span class="ss">inclusion: </span><span class="p">[</span><span class="kp">true</span><span class="p">,</span> <span class="kp">false</span><span class="p">]</span>
<span class="c1"># El valor _no debe_ ser nil, es decir, true o false</span>
<span class="n">validates</span> <span class="ss">:boolean_field_name</span><span class="p">,</span> <span class="ss">exclusion: </span><span class="p">[</span><span class="kp">nil</span><span class="p">]</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="# El valor _debe_ ser true o false
validates :boolean_field_name, inclusion: [true, false]
# El valor _no debe_ ser nil, es decir, true o false
validates :boolean_field_name, exclusion: [nil]
">Copy</button>
</div>
<p>Al usar una de estas validaciones, te asegurarás de que el valor NO sea <code>nil</code>, lo que resultaría en un valor <code>NULL</code> en la mayoría de los casos.</p><p>El mensaje de error predeterminado es <em>"can't be blank"</em>.</p><h3 id="absence"><a class="anchorlink" href="#absence"><span>2.10</span> <code>absence</code></a></h3><p>Este ayudante valida que los atributos especificados estén ausentes. Utiliza el método <a href="https://edgeapi.rubyonrails.org/classes/Object.html#method-i-present-3F"><code>Object#present?</code></a> para comprobar si el valor no es <code>nil</code> o una cadena vacía, es decir, una cadena que esté vacía o que consista solo en espacios en blanco.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:login</span><span class="p">,</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">absence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, :login, :email, absence: true
end
">Copy</button>
</div>
<p>Si deseas asegurarte de que una asociación esté ausente, necesitarás verificar si el objeto asociado en sí está ausente, y no solo la clave foránea utilizada para mapear la asociación.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">LineItem</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">belongs_to</span> <span class="ss">:order</span>
<span class="n">validates</span> <span class="ss">:order</span><span class="p">,</span> <span class="ss">absence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class LineItem < ApplicationRecord
belongs_to :order
validates :order, absence: true
end
">Copy</button>
</div>
<p>Para validar registros asociados cuya ausencia es requerida, debes especificar la opción <code>:inverse_of</code> para la asociación:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Order</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">has_many</span> <span class="ss">:line_items</span><span class="p">,</span> <span class="ss">inverse_of: :order</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Order < ApplicationRecord
has_many :line_items, inverse_of: :order
end
">Copy</button>
</div>
<p>NOTA: Si deseas asegurarte de que la asociación esté tanto presente como válida, también necesitas usar <code>validates_associated</code>. Más sobre eso <a href="#validates-associated">abajo</a>.</p><p>Si validas la ausencia de un objeto asociado a través de una relación <code>has_one</code> o <code>has_many</code>, verificará que el objeto no sea <code>present?</code> ni <code>marked_for_destruction?</code>.</p><p>Dado que <code>false.present?</code> es false, si deseas validar la ausencia de un campo booleano, debes usar <code>validates :field_name, exclusion: { in: [true, false] }</code>.</p><p>El mensaje de error predeterminado es <em>"must be blank"</em>.</p><h3 id="uniqueness"><a class="anchorlink" href="#uniqueness"><span>2.11</span> <code>uniqueness</code></a></h3><p>Este ayudante valida que el valor del atributo sea único justo antes de que el objeto se guarde.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Account</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">uniqueness: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Account < ApplicationRecord
validates :email, uniqueness: true
end
">Copy</button>
</div>
<p>La validación ocurre realizando una consulta SQL en la tabla del modelo, buscando un registro existente con el mismo valor en ese atributo.</p><p>Hay una opción <code>:scope</code> que puedes usar para especificar uno o más atributos que se utilizan para limitar la verificación de unicidad:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Holiday</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">uniqueness: </span><span class="p">{</span> <span class="ss">scope: :year</span><span class="p">,</span>
<span class="ss">message: </span><span class="s2">"should happen once per year"</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Holiday < ApplicationRecord
validates :name, uniqueness: { scope: :year,
message: "should happen once per year" }
end
">Copy</button>
</div>
<p>ADVERTENCIA. Esta validación no crea una restricción de unicidad en la base de datos, por lo que puede suceder que dos conexiones diferentes a la base de datos creen dos registros con el mismo valor para una columna que deseas que sea única. Para evitar eso, debes crear un índice único en esa columna en tu base de datos.</p><p>Para agregar una restricción de unicidad en tu base de datos, usa la declaración <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index"><code>add_index</code></a> en una migración e incluye la opción <code>unique: true</code>.</p><p>Si deseas crear una restricción de base de datos para evitar posibles violaciones de una validación de unicidad usando la opción <code>:scope</code>, debes crear un índice único en ambas columnas en tu base de datos. Consulta <a href="https://dev.mysql.com/doc/refman/en/multiple-column-indexes.html">el manual de MySQL</a> y <a href="https://mariadb.com/kb/en/compound-composite-indexes/">el manual de MariaDB</a> para obtener más detalles sobre índices de columnas múltiples, o <a href="https://www.postgresql.org/docs/current/static/ddl-constraints.html">el manual de PostgreSQL</a> para ejemplos de restricciones únicas que se refieren a un grupo de columnas.</p><p>También hay una opción <code>:case_sensitive</code> que puedes usar para definir si la restricción de unicidad será sensible a mayúsculas, insensible a mayúsculas o si debe respetar la colación predeterminada de la base de datos. Esta opción por defecto es respetar la colación predeterminada de la base de datos.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">uniqueness: </span><span class="p">{</span> <span class="ss">case_sensitive: </span><span class="kp">false</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :name, uniqueness: { case_sensitive: false }
end
">Copy</button>
</div>
<p>ADVERTENCIA. Ten en cuenta que algunas bases de datos están configuradas para realizar búsquedas insensibles a mayúsculas de todos modos.</p><p>Hay una opción <code>:conditions</code> que puedes especificar como un fragmento SQL <code>WHERE</code> para limitar la búsqueda de la restricción de unicidad (por ejemplo, <code>conditions: -> { where(status: 'active') }</code>).</p><p>El mensaje de error predeterminado es <em>"has already been taken"</em>.</p><p>Consulta <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of"><code>validates_uniqueness_of</code></a> para obtener más información.</p><h3 id="validates-associated"><a class="anchorlink" href="#validates-associated"><span>2.12</span> <code>validates_associated</code></a></h3><p>Debes usar este ayudante cuando tu modelo tenga asociaciones que siempre necesiten ser validadas. Cada vez que intentes guardar tu objeto, se llamará a <code>valid?</code> en cada uno de los objetos asociados.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Library</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">has_many</span> <span class="ss">:books</span>
<span class="n">validates_associated</span> <span class="ss">:books</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Library < ApplicationRecord
has_many :books
validates_associated :books
end
">Copy</button>
</div>
<p>Esta validación funcionará con todos los tipos de asociación.</p><p>PRECAUCIÓN: No uses <code>validates_associated</code> en ambos extremos de tus asociaciones. Se llamarían entre sí en un bucle infinito.</p><p>El mensaje de error predeterminado para <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_associated"><code>validates_associated</code></a> es <em>"is invalid"</em>. Ten en cuenta que cada objeto asociado contendrá su propia colección <code>errors</code>; los errores no se propagan al modelo que llama.</p><p>NOTA: <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_associated"><code>validates_associated</code></a> solo se puede usar con objetos ActiveRecord, hasta ahora todo lo mencionado también se puede usar en cualquier objeto que incluya <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations.html"><code>ActiveModel::Validations</code></a>.</p><h3 id="validates-each"><a class="anchorlink" href="#validates-each"><span>2.13</span> <code>validates_each</code></a></h3><p>Este ayudante valida atributos contra un bloque. No tiene una función de validación predefinida. Debes crear una usando un bloque, y cada atributo pasado a <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates_each"><code>validates_each</code></a> será probado contra él.</p><p>En el siguiente ejemplo, rechazaremos nombres y apellidos que comiencen con minúsculas.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates_each</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:surname</span> <span class="k">do</span> <span class="o">|</span><span class="n">record</span><span class="p">,</span> <span class="kp">attr</span><span class="p">,</span> <span class="n">value</span><span class="o">|</span>
<span class="n">record</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="kp">attr</span><span class="p">,</span> <span class="s1">'must start with upper case'</span><span class="p">)</span> <span class="k">if</span> <span class="sr">/\A[[:lower:]]/</span><span class="p">.</span><span class="nf">match?</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates_each :name, :surname do |record, attr, value|
record.errors.add(attr, 'must start with upper case') if /\A[[:lower:]]/.match?(value)
end
end
">Copy</button>
</div>
<p>El bloque recibe el registro, el nombre del atributo y el valor del atributo.</p><p>Puedes hacer cualquier cosa que desees para verificar datos válidos dentro del bloque. Si tu validación falla, debes agregar un error al modelo, haciéndolo inválido.</p><h3 id="validates-with"><a class="anchorlink" href="#validates-with"><span>2.14</span> <code>validates_with</code></a></h3><p>Este ayudante pasa el registro a una clase separada para la validación.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">GoodnessValidator</span> <span class="o"><</span> <span class="no">ActiveModel</span><span class="o">::</span><span class="no">Validator</span>
<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
<span class="k">if</span> <span class="n">record</span><span class="p">.</span><span class="nf">first_name</span> <span class="o">==</span> <span class="s2">"Evil"</span>
<span class="n">record</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">add</span> <span class="ss">:base</span><span class="p">,</span> <span class="s2">"This person is evil"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates_with</span> <span class="no">GoodnessValidator</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class GoodnessValidator < ActiveModel::Validator
def validate(record)
if record.first_name == "Evil"
record.errors.add :base, "This person is evil"
end
end
end
class Person < ApplicationRecord
validates_with GoodnessValidator
end
">Copy</button>
</div>
<p>No hay mensaje de error predeterminado para <code>validates_with</code>. Debes agregar manualmente errores a la colección <code>errors</code> del registro en la clase del validador.</p><p>NOTA: Los errores agregados a <code>record.errors[:base]</code> se relacionan con el estado del registro en su conjunto.</p><p>Para implementar el método de validación, debes aceptar un parámetro <code>record</code> en la definición del método, que es el registro a validar.</p><p>Si deseas agregar un error en un atributo específico, pásalo como primer argumento, como <code>record.errors.add(:first_name, "please choose another name")</code>. Cubriremos <a href="#working-with-validation-errors">errores de validación</a> en mayor detalle más adelante.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
<span class="k">if</span> <span class="n">record</span><span class="p">.</span><span class="nf">some_field</span> <span class="o">!=</span> <span class="s2">"acceptable"</span>
<span class="n">record</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">add</span> <span class="ss">:some_field</span><span class="p">,</span> <span class="s2">"this field is unacceptable"</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="def validate(record)
if record.some_field != "acceptable"
record.errors.add :some_field, "this field is unacceptable"
end
end
">Copy</button>
</div>
<p>El ayudante <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates_with"><code>validates_with</code></a> toma una clase, o una lista de clases para usar en la validación.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates_with</span> <span class="no">MyValidator</span><span class="p">,</span> <span class="no">MyOtherValidator</span><span class="p">,</span> <span class="ss">on: :create</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates_with MyValidator, MyOtherValidator, on: :create
end
">Copy</button>
</div>
<p>Como todas las demás validaciones, <code>validates_with</code> toma las opciones <code>:if</code>, <code>:unless</code> y <code>:on</code>. Si pasas cualquier otra opción, las enviará a la clase del validador como <code>options</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">GoodnessValidator</span> <span class="o"><</span> <span class="no">ActiveModel</span><span class="o">::</span><span class="no">Validator</span>
<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
<span class="k">if</span> <span class="n">options</span><span class="p">[</span><span class="ss">:fields</span><span class="p">].</span><span class="nf">any?</span> <span class="p">{</span> <span class="o">|</span><span class="n">field</span><span class="o">|</span> <span class="n">record</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">field</span><span class="p">)</span> <span class="o">==</span> <span class="s2">"Evil"</span> <span class="p">}</span>
<span class="n">record</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">add</span> <span class="ss">:base</span><span class="p">,</span> <span class="s2">"This person is evil"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates_with</span> <span class="no">GoodnessValidator</span><span class="p">,</span> <span class="ss">fields: </span><span class="p">[</span><span class="ss">:first_name</span><span class="p">,</span> <span class="ss">:last_name</span><span class="p">]</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class GoodnessValidator < ActiveModel::Validator
def validate(record)
if options[:fields].any? { |field| record.send(field) == "Evil" }
record.errors.add :base, "This person is evil"
end
end
end
class Person < ApplicationRecord
validates_with GoodnessValidator, fields: [:first_name, :last_name]
end
">Copy</button>
</div>
<p>Ten en cuenta que el validador se inicializará <em>solo una vez</em> para todo el ciclo de vida de la aplicación, y no en cada ejecución de validación, así que ten cuidado al usar variables de instancia dentro de él.</p><p>Si tu validador es lo suficientemente complejo como para que desees variables de instancia, puedes usar fácilmente un objeto Ruby normal en su lugar:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validate</span> <span class="k">do</span> <span class="o">|</span><span class="n">person</span><span class="o">|</span>
<span class="no">GoodnessValidator</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">person</span><span class="p">).</span><span class="nf">validate</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">GoodnessValidator</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">person</span><span class="p">)</span>
<span class="vi">@person</span> <span class="o">=</span> <span class="n">person</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">validate</span>
<span class="k">if</span> <span class="n">some_complex_condition_involving_ivars_and_private_methods?</span>
<span class="vi">@person</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">add</span> <span class="ss">:base</span><span class="p">,</span> <span class="s2">"This person is evil"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># ...</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validate do |person|
GoodnessValidator.new(person).validate
end
end
class GoodnessValidator
def initialize(person)
@person = person
end
def validate
if some_complex_condition_involving_ivars_and_private_methods?
@person.errors.add :base, "This person is evil"
end
end
# ...
end
">Copy</button>
</div>
<p>Cubriremos <a href="#realizando-validaciones-personalizadas">validaciones personalizadas</a> más adelante.</p><h2 id="opciones-comunes-de-validación"><a class="anchorlink" href="#opciones-comunes-de-validación"><span>3</span> Opciones Comunes de Validación</a></h2><p>Hay varias opciones comunes compatibles con los validadores que acabamos de revisar, ¡vamos a repasarlas ahora!</p><p>NOTA: No todas estas opciones son compatibles con cada validador, consulta la documentación de la API para <a href="https://edgeapi.rubyonrails.org/classes/ActiveModel/Validations.html"><code>ActiveModel::Validations</code></a>.</p><p>Al usar cualquiera de los métodos de validación que acabamos de mencionar, también hay una lista de opciones comunes compartidas junto con los validadores. ¡Las cubriremos ahora!</p>
<ul>
<li><a href="#allow-nil"><code>:allow_nil</code></a>: Omite la validación si el atributo es <code>nil</code>.</li>
<li><a href="#allow-blank"><code>:allow_blank</code></a>: Omite la validación si el atributo está en blanco.</li>
<li><a href="#message"><code>:message</code></a>: Especifica un mensaje de error personalizado.</li>
<li><a href="#on"><code>:on</code></a>: Especifica los contextos donde esta validación está activa.</li>
<li><a href="#validaciones-estrictas"><code>:strict</code></a>: Lanza una excepción cuando la validación falla.</li>
<li><a href="#validación-condicional"><code>:if</code> y <code>:unless</code></a>: Especifica cuándo la validación debe o no debe ocurrir.</li>
</ul>
<h3 id="allow-nil"><a class="anchorlink" href="#allow-nil"><span>3.1</span> <code>:allow_nil</code></a></h3><p>La opción <code>:allow_nil</code> omite la validación cuando el valor que se está validando es <code>nil</code>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Coffee</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:size</span><span class="p">,</span> <span class="ss">inclusion: </span><span class="p">{</span> <span class="ss">in: </span><span class="sx">%w(small medium large)</span><span class="p">,</span>
<span class="ss">message: </span><span class="s2">"%{value} is not a valid size"</span> <span class="p">},</span> <span class="ss">allow_nil: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value} is not a valid size" }, allow_nil: true
end
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Coffee</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">size: </span><span class="kp">nil</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">true</span>
<span class="gp">irb></span><span class="w"> </span><span class="no">Coffee</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">size: </span><span class="s2">"mega"</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">false</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Coffee.create(size: nil).valid?
Coffee.create(size: "mega").valid?
">Copy</button>
</div>
<p>Para ver todas las opciones del argumento del mensaje, consulta la <a href="#message">documentación del mensaje</a>.</p><h3 id="allow-blank"><a class="anchorlink" href="#allow-blank"><span>3.2</span> <code>:allow_blank</code></a></h3><p>La opción <code>:allow_blank</code> es similar a la opción <code>:allow_nil</code>. Esta opción permitirá que la validación pase si el valor del atributo es <code>blank?</code>, como <code>nil</code> o una cadena vacía, por ejemplo.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Topic</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:title</span><span class="p">,</span> <span class="ss">length: </span><span class="p">{</span> <span class="ss">is: </span><span class="mi">5</span> <span class="p">},</span> <span class="ss">allow_blank: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Topic < ApplicationRecord
validates :title, length: { is: 5 }, allow_blank: true
end
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight irb"><span class="gp">irb></span><span class="w"> </span><span class="no">Topic</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">title: </span><span class="s2">""</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">true</span>
<span class="gp">irb></span><span class="w"> </span><span class="no">Topic</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">title: </span><span class="kp">nil</span><span class="p">).</span><span class="nf">valid?</span>
<span class="p">=></span> <span class="kp">true</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="Topic.create(title: "").valid?
Topic.create(title: nil).valid?
">Copy</button>
</div>
<h3 id="message"><a class="anchorlink" href="#message"><span>3.3</span> <code>:message</code></a></h3><p>Como ya has visto, la opción <code>:message</code> te permite especificar el mensaje que se agregará a la colección <code>errors</code> cuando la validación falle. Cuando no se usa esta opción, Active Record usará el mensaje de error predeterminado respectivo para cada ayudante de validación.</p><p>La opción <code>:message</code> acepta un <code>String</code> o <code>Proc</code> como su valor.</p><p>Un valor de <code>String</code> para <code>:message</code> puede contener opcionalmente cualquiera/todos de <code>%{value}</code>, <code>%{attribute}</code> y <code>%{model}</code>, que serán reemplazados dinámicamente cuando la validación falle. Este reemplazo se realiza usando la gema i18n, y los marcadores de posición deben coincidir exactamente, no se permiten espacios.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="c1"># Mensaje codificado</span>
<span class="n">validates</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">presence: </span><span class="p">{</span> <span class="ss">message: </span><span class="s2">"must be given please"</span> <span class="p">}</span>
<span class="c1"># Mensaje con valor de atributo dinámico. %{value} será reemplazado</span>
<span class="c1"># con el valor real del atributo. %{attribute} y %{model}</span>
<span class="c1"># también están disponibles.</span>
<span class="n">validates</span> <span class="ss">:age</span><span class="p">,</span> <span class="ss">numericality: </span><span class="p">{</span> <span class="ss">message: </span><span class="s2">"%{value} seems wrong"</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
# Mensaje codificado
validates :name, presence: { message: "must be given please" }
# Mensaje con valor de atributo dinámico. %{value} será reemplazado
# con el valor real del atributo. %{attribute} y %{model}
# también están disponibles.
validates :age, numericality: { message: "%{value} seems wrong" }
end
">Copy</button>
</div>
<p>Un valor de <code>Proc</code> para <code>:message</code> recibe dos argumentos: el objeto que se está validando y un hash con pares clave-valor <code>:model</code>, <code>:attribute</code> y <code>:value</code>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:username</span><span class="p">,</span>
<span class="ss">uniqueness: </span><span class="p">{</span>
<span class="c1"># objeto = objeto persona que se está validando</span>
<span class="c1"># datos = { model: "Person", attribute: "Username", value: <username> }</span>
<span class="ss">message: </span><span class="o">-></span><span class="p">(</span><span class="n">object</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span> <span class="k">do</span>
<span class="s2">"Hey </span><span class="si">#{</span><span class="n">object</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">, </span><span class="si">#{</span><span class="n">data</span><span class="p">[</span><span class="ss">:value</span><span class="p">]</span><span class="si">}</span><span class="s2"> is already taken."</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Person < ApplicationRecord
validates :username,
uniqueness: {
# objeto = objeto persona que se está validando
# datos = { model: "Person", attribute: "Username", value: <username> }
message: ->(object, data) do
"Hey #{object.name}, #{data[:value]} is already taken."
end
}
end
">Copy</button>
</div>
<h3 id="on"><a class="anchorlink" href="#on"><span>3.4</span> <code>:on</code></a></h3><p>La opción <code>:on</code> te permite especificar cuándo debe suceder la validación. El comportamiento predeterminado para todos los ayudantes de validación integrados es ejecutarse al guardar (tanto cuando estás creando un nuevo registro como cuando lo estás actualizando). Si deseas cambiarlo, puedes usar <code>on: :create</code> para ejecutar la validación solo cuando se crea un nuevo registro o <code>on: :update</code> para ejecutar la validación solo cuando se actualiza un registro.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Person</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>