-
Notifications
You must be signed in to change notification settings - Fork 0
/
active_record_migrations.html
943 lines (858 loc) · 72.4 KB
/
active_record_migrations.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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>액티브 레코드 마이그레이션 — Ruby on Rails Guides</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style.css" data-turbolinks-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print">
<link rel="stylesheet" type="text/css" href="stylesheets/syntaxhighlighter/shCore.css" data-turbolinks-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/syntaxhighlighter/shThemeRailsGuides.css" data-turbolinks-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/fixes.css" data-turbolinks-track="reload">
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<script src="javascripts/syntaxhighlighter.js" data-turbolinks-track="reload"></script>
<script src="javascripts/turbolinks.js" data-turbolinks-track="reload"></script>
<script src="javascripts/guides.js" data-turbolinks-track="reload"></script>
<script src="javascripts/responsive-tables.js" data-turbolinks-track="reload"></script>
<meta property="og:title" content="액티브 레코드 마이그레이션 — Ruby on Rails Guides" />
<meta name="description" content="액티브 레코드 마이그레이션마이그레이션은 시간이 지남에 따라 데이터베이스 스키마를 발전시킬 수 있는 액티브 레코드의 특수한 기능이다. 순수 SQL로 스키마 수정을 작성하는 대신 마이그레이션을 통해 쉬운 루비 DSL을 사용하여 테이블의 변경 사항을 기술할 수 있다.이 가이드를 읽은 후에는 아래의 내용을 알게 될 것이다. 마이그레이션을 생성할 때 사용하는 생성자 데이터베이스를 다루기 위해서 액티브 레코드가 제공하는 메소드 마이그레이션과 스키마를 다루는 레일스 명령어 마이그레이션이 schema.rb와 연관되는 방법" />
<meta property="og:description" content="액티브 레코드 마이그레이션마이그레이션은 시간이 지남에 따라 데이터베이스 스키마를 발전시킬 수 있는 액티브 레코드의 특수한 기능이다. 순수 SQL로 스키마 수정을 작성하는 대신 마이그레이션을 통해 쉬운 루비 DSL을 사용하여 테이블의 변경 사항을 기술할 수 있다.이 가이드를 읽은 후에는 아래의 내용을 알게 될 것이다. 마이그레이션을 생성할 때 사용하는 생성자 데이터베이스를 다루기 위해서 액티브 레코드가 제공하는 메소드 마이그레이션과 스키마를 다루는 레일스 명령어 마이그레이션이 schema.rb와 연관되는 방법" />
<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" />
</head>
<body class="guide">
<div id="topNav">
<div class="wrapper">
<strong class="more-info-label">공식 웹사이트 <a href="https://rubyonrails.org/">rubyonrails.org:</a> </strong>
<span class="red-button more-info-button">
루비온레일스 웹사이트
</span>
<ul class="more-info-links s-hidden">
<li class="more-info"><a href="https://weblog.rubyonrails.org/">블로그</a></li>
<li class="more-info"><a href="https://guides.rubyonrails.org/">영문가이드</a></li>
<li class="more-info"><a href="https://api.rubyonrails.org/">레일스API</a></li>
<li class="more-info"><a href="https://stackoverflow.com/questions/tagged/ruby-on-rails">질문하기</a></li>
<li class="more-info"><a href="https://github.com/rails/rails">GitHub에서 기여하기</a></li>
</ul>
</div>
</div>
<div id="header">
<div class="wrapper clearfix">
<h1><a href="index.html" title="Return to home page">Guides.rubyonrails.org</a></h1>
<ul class="nav">
<li><a class="nav-item" href="index.html">홈</a></li>
<li class="guides-index guides-index-large">
<a href="index.html" id="guidesMenu" class="guides-index-item nav-item">가이드 인덱스</a>
<div id="guides" class="clearfix" style="display: none;">
<hr />
<div class="guides-section-container">
<div class="guides-section">
<dt>시작하면서</dt>
<dd><a href="getting_started.html">레일스로 시작하기</a></dd>
</div>
<div class="guides-section">
<dt>모델</dt>
<dd><a href="active_record_basics.html">액티브 레코드 기본</a></dd>
<dd><a href="active_record_migrations.html">액티브 레코드 마이그레이션</a></dd>
<dd><a href="active_record_validations.html">액티브 레코드 유효성 검증</a></dd>
<dd><a href="active_record_callbacks.html">액티브 레코드 콜백</a></dd>
<dd><a href="association_basics.html">Active Record Associations</a></dd>
<dd><a href="active_record_querying.html">Active Record Query Interface</a></dd>
</div>
<div class="guides-section">
<dt>Views</dt>
<dd><a href="layouts_and_rendering.html">Layouts and Rendering in Rails</a></dd>
<dd><a href="form_helpers.html">Action View Form Helpers</a></dd>
</div>
<div class="guides-section">
<dt>Controllers</dt>
<dd><a href="action_controller_overview.html">Action Controller Overview</a></dd>
<dd><a href="routing.html">Rails Routing from the Outside In</a></dd>
</div>
<div class="guides-section">
<dt>Other Components</dt>
<dd><a href="active_support_core_extensions.html">Active Support Core Extensions</a></dd>
<dd><a href="action_mailer_basics.html">Action Mailer Basics</a></dd>
<dd><a href="active_job_basics.html">Active Job Basics</a></dd>
<dd><a href="active_storage_overview.html">Active Storage Overview</a></dd>
<dd><a href="action_cable_overview.html">Action Cable Overview</a></dd>
</div>
<div class="guides-section">
<dt>Digging Deeper</dt>
<dd><a href="i18n.html">Rails Internationalization (I18n) API</a></dd>
<dd><a href="testing.html">Testing Rails Applications</a></dd>
<dd><a href="security.html">Securing Rails Applications</a></dd>
<dd><a href="debugging_rails_applications.html">Debugging Rails Applications</a></dd>
<dd><a href="configuring.html">Configuring Rails Applications</a></dd>
<dd><a href="command_line.html">The Rails Command Line</a></dd>
<dd><a href="asset_pipeline.html">The Asset Pipeline</a></dd>
<dd><a href="working_with_javascript_in_rails.html">Working with JavaScript in Rails</a></dd>
<dd><a href="autoloading_and_reloading_constants.html">Autoloading and Reloading Constants (Zeitwerk Mode)</a></dd>
<dd><a href="autoloading_and_reloading_constants_classic_mode.html">Autoloading and Reloading Constants (Classic Mode)</a></dd>
<dd><a href="caching_with_rails.html">Caching with Rails: An Overview</a></dd>
<dd><a href="api_app.html">Using Rails for API-only Applications</a></dd>
</div>
<div class="guides-section">
<dt>Extending Rails</dt>
<dd><a href="rails_on_rack.html">Rails on Rack</a></dd>
<dd><a href="generators.html">Creating and Customizing Rails Generators & Templates</a></dd>
</div>
<div class="guides-section">
<dt>Contributions</dt>
<dd><a href="contributing_to_ruby_on_rails.html">Contributing to Ruby on Rails</a></dd>
<dd><a href="api_documentation_guidelines.html">API Documentation Guidelines</a></dd>
<dd><a href="ruby_on_rails_guides_guidelines.html">Guides Guidelines</a></dd>
</div>
<div class="guides-section">
<dt>Policies</dt>
<dd><a href="maintenance_policy.html">Maintenance Policy</a></dd>
</div>
<div class="guides-section">
<dt>Release Notes</dt>
<dd><a href="upgrading_ruby_on_rails.html">Upgrading Ruby on Rails</a></dd>
<dd><a href="6_0_release_notes.html">Version 6.0 - August 2019</a></dd>
<dd><a href="5_2_release_notes.html">Version 5.2 - April 2018</a></dd>
<dd><a href="5_1_release_notes.html">Version 5.1 - April 2017</a></dd>
<dd><a href="5_0_release_notes.html">Version 5.0 - June 2016</a></dd>
<dd><a href="4_2_release_notes.html">Version 4.2 - December 2014</a></dd>
<dd><a href="4_1_release_notes.html">Version 4.1 - April 2014</a></dd>
<dd><a href="4_0_release_notes.html">Version 4.0 - June 2013</a></dd>
<dd><a href="3_2_release_notes.html">Version 3.2 - January 2012</a></dd>
<dd><a href="3_1_release_notes.html">Version 3.1 - August 2011</a></dd>
<dd><a href="3_0_release_notes.html">Version 3.0 - August 2010</a></dd>
<dd><a href="2_3_release_notes.html">Version 2.3 - March 2009</a></dd>
<dd><a href="2_2_release_notes.html">Version 2.2 - November 2008</a></dd>
</div>
</div>
</div>
</li>
<li><a class="nav-item" href="contributing_to_ruby_on_rails.html">기여하기</a></li>
<li class="guides-index guides-index-small">
<select class="guides-index-item nav-item">
<option value="index.html">가이드 인덱스</option>
<optgroup label="시작하면서">
<option value="getting_started.html">레일스로 시작하기</option>
</optgroup>
<optgroup label="모델">
<option value="active_record_basics.html">액티브 레코드 기본</option>
<option value="active_record_migrations.html">액티브 레코드 마이그레이션</option>
<option value="active_record_validations.html">액티브 레코드 유효성 검증</option>
<option value="active_record_callbacks.html">액티브 레코드 콜백</option>
<option value="association_basics.html">Active Record Associations</option>
<option value="active_record_querying.html">Active Record Query Interface</option>
</optgroup>
<optgroup label="Views">
<option value="layouts_and_rendering.html">Layouts and Rendering in Rails</option>
<option value="form_helpers.html">Action View Form Helpers</option>
</optgroup>
<optgroup label="Controllers">
<option value="action_controller_overview.html">Action Controller Overview</option>
<option value="routing.html">Rails Routing from the Outside In</option>
</optgroup>
<optgroup label="Other Components">
<option value="active_support_core_extensions.html">Active Support Core Extensions</option>
<option value="action_mailer_basics.html">Action Mailer Basics</option>
<option value="active_job_basics.html">Active Job Basics</option>
<option value="active_storage_overview.html">Active Storage Overview</option>
<option value="action_cable_overview.html">Action Cable Overview</option>
</optgroup>
<optgroup label="Digging Deeper">
<option value="i18n.html">Rails Internationalization (I18n) API</option>
<option value="testing.html">Testing Rails Applications</option>
<option value="security.html">Securing Rails Applications</option>
<option value="debugging_rails_applications.html">Debugging Rails Applications</option>
<option value="configuring.html">Configuring Rails Applications</option>
<option value="command_line.html">The Rails Command Line</option>
<option value="asset_pipeline.html">The Asset Pipeline</option>
<option value="working_with_javascript_in_rails.html">Working with JavaScript in Rails</option>
<option value="autoloading_and_reloading_constants.html">Autoloading and Reloading Constants (Zeitwerk Mode)</option>
<option value="autoloading_and_reloading_constants_classic_mode.html">Autoloading and Reloading Constants (Classic Mode)</option>
<option value="caching_with_rails.html">Caching with Rails: An Overview</option>
<option value="api_app.html">Using Rails for API-only Applications</option>
</optgroup>
<optgroup label="Extending Rails">
<option value="rails_on_rack.html">Rails on Rack</option>
<option value="generators.html">Creating and Customizing Rails Generators & Templates</option>
</optgroup>
<optgroup label="Contributions">
<option value="contributing_to_ruby_on_rails.html">Contributing to Ruby on Rails</option>
<option value="api_documentation_guidelines.html">API Documentation Guidelines</option>
<option value="ruby_on_rails_guides_guidelines.html">Guides Guidelines</option>
</optgroup>
<optgroup label="Policies">
<option value="maintenance_policy.html">Maintenance Policy</option>
</optgroup>
<optgroup label="Release Notes">
<option value="upgrading_ruby_on_rails.html">Upgrading Ruby on Rails</option>
<option value="6_0_release_notes.html">Version 6.0 - August 2019</option>
<option value="5_2_release_notes.html">Version 5.2 - April 2018</option>
<option value="5_1_release_notes.html">Version 5.1 - April 2017</option>
<option value="5_0_release_notes.html">Version 5.0 - June 2016</option>
<option value="4_2_release_notes.html">Version 4.2 - December 2014</option>
<option value="4_1_release_notes.html">Version 4.1 - April 2014</option>
<option value="4_0_release_notes.html">Version 4.0 - June 2013</option>
<option value="3_2_release_notes.html">Version 3.2 - January 2012</option>
<option value="3_1_release_notes.html">Version 3.1 - August 2011</option>
<option value="3_0_release_notes.html">Version 3.0 - August 2010</option>
<option value="2_3_release_notes.html">Version 2.3 - March 2009</option>
<option value="2_2_release_notes.html">Version 2.2 - November 2008</option>
</optgroup>
</select>
</li>
</ul>
</div>
</div>
<hr class="hide" />
<div id="feature">
<div class="wrapper">
<h2 id="active-record-migrations">액티브 레코드 마이그레이션</h2><p>마이그레이션은 시간이 지남에 따라 데이터베이스 스키마를 발전시킬 수 있는 액티브 레코드의 특수한 기능이다. 순수 SQL로 스키마 수정을 작성하는 대신 마이그레이션을 통해 쉬운 루비 DSL을 사용하여 테이블의 변경 사항을 기술할 수 있다.</p><p>이 가이드를 읽은 후에는 아래의 내용을 알게 될 것이다.</p>
<ul>
<li>마이그레이션을 생성할 때 사용하는 생성자</li>
<li>데이터베이스를 다루기 위해서 액티브 레코드가 제공하는 메소드</li>
<li>마이그레이션과 스키마를 다루는 레일스 명령어</li>
<li>마이그레이션이 <code>schema.rb</code>와 연관되는 방법</li>
</ul>
<div id="subCol">
<h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
<ol class="chapters">
<li><a href="#migration-overview">마이그레이션 개요</a></li>
<li>
<a href="#creating-a-migration">마이그레이션 작성하기</a>
<ul>
<li><a href="#creating-a-standalone-migration">별도의 마이그레이션 파일 작성하기</a></li>
<li><a href="#model-generators">모델 생성자</a></li>
<li><a href="#passing-modifiers">데이터형 변경자 지정하기</a></li>
</ul>
</li>
<li>
<a href="#writing-a-migration">마이그레이션 작성하기</a>
<ul>
<li><a href="#creating-a-table">테이블 생성하기</a></li>
<li><a href="#creating-a-join-table">조인 테이블 생성하기</a></li>
<li><a href="#changing-tables">테이블 변경하기</a></li>
<li><a href="#changing-columns">컬럼 변경하기</a></li>
<li><a href="#column-modifiers">컬럼 변경자</a></li>
<li><a href="#foreign-keys">외래키</a></li>
<li><a href="#when-helpers-aren't-enough">헬퍼 메소드가 충분히 않을 때</a></li>
<li><a href="#using-the-change-method"><code>change</code> 메소드 사용하기</a></li>
<li><a href="#using-reversible"><code>reversible</code> 메소드 사용하기</a></li>
<li><a href="#using-the-up/down-methods"><code>up</code>/<code>down</code> 메소드 사용하기</a></li>
<li><a href="#reverting-previous-migrations">이전 마이그레이션 되돌리기</a></li>
</ul>
</li>
<li>
<a href="#running-migrations">마이그레이션 실행하기</a>
<ul>
<li><a href="#rolling-back">롤백하기</a></li>
<li><a href="#setup-the-database">데이터베이스 셋업하기</a></li>
<li><a href="#resetting-the-database">데이터베이스 재설정(reset)하기</a></li>
<li><a href="#running-specific-migrations">특정 마이그레이션 실행하기</a></li>
<li><a href="#running-migrations-in-different-environments">환경별로 마이그레이션 실행하기</a></li>
<li><a href="#changing-the-output-of-running-migrations">마이그레이션 실행 결과 변경하기</a></li>
</ul>
</li>
<li><a href="#changing-existing-migrations">기존 마이그레이션 변경하기</a></li>
<li>
<a href="#schema-dumping-and-you">스키마 덤핑과 개발자</a>
<ul>
<li><a href="#what-are-schema-files-for?">스키마 파일의 목적</a></li>
<li><a href="#types-of-schema-dumps">스키마 덤프의 형식</a></li>
<li><a href="#schema-dumps-and-source-control">스키마 덤프와 소스 컨트롤</a></li>
</ul>
</li>
<li><a href="#active-record-and-referential-integrity">액티브 레코드와 참조 무결성</a></li>
<li><a href="#migrations-and-seed-data">마이그레이션과 시드 데이터</a></li>
<li><a href="#old-migrations">과거 마이그레이션</a></li>
</ol>
</div>
</div>
</div>
<div id="container">
<div class="wrapper">
<div id="mainCol">
<h3 id="migration-overview"><a class="anchorlink" href="#migration-overview">1 마이그레이션 개요</a></h3><p>마이그레이션은 일관되고 쉬운 방법으로 <a href="https://en.wikipedia.org/wiki/Schema_migration">시간이 지남에 따라 데이터베이스 스키마를 변경</a>하는 편리한 방법이다. SQL을 직접 작성하지 않고 루비 DSL을 사용하므로 스키마와 변경 사항을 데이터베이스와 독립적으로 만들 수 있다.</p><p>각 마이그레이션을 데이터베이스의 새로운 '버전'으로 생각할 수 있다. 스키마는 아무 것도 없이 시작하며 각 마이그레이션은 테이블, 컬럼 또는 항목을 추가하거나 제거하도록 스키마를 수정한다. 액티브 레코드는 이와 같은 마이그레이션 타임 라인에 따라 스키마를 업데이트하는 방법을 알고 있으며 히스토리 상의 어느 지점에 있더라도 최신 버전으로 유지한다. 액티브 레코드는 또한 데이터베이스의 최신 구조와 일치하도록 <code>db/schema.rb</code> 파일을 업데이트 할 것이다.</p><p>마이그레이션의 예는 아래와 같다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class CreateProducts < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
</pre>
</div>
<p>이 마이그레이션은 <code>name</code>이라는 문자열 컬럼과 <code>description</code>이라는 텍스트 컬럼으로 구성된 <code>products</code>라는 테이블을 추가한다. <code>id</code>라는 기본키 컬럼도 모든 액티브 레코드 모델의 기본 기본키이므로 암시적으로 추가된다. <code>timestamps</code> 매크로는 <code>created_at</code>와m<code>updated_at</code>의 두 컬럼을 추가한다. 이러한 특수 컬럼이 존재하는 경우 액티브 레코드에 의해 자동으로 관리된다.</p><p>앞으로 진행되기를 바라는 변경 내용을 미리 정의한다는 것에 주목한다. 이 마이그레이션이 실행되기 전에는 테이블이 존재하지 않는다. 그 후에 테이블이 존재한다. 액티브 레코드는 이 마이그레이션을 돌이키는 방법도 알고 있다. 즉, 이 마이그레이션을 롤백하면 테이블이 제거될 것이다.</p><p>스키마를 변경하는 SQL문에 트랜잭션을 지원하는 데이터베이스에서는 트랜잭션이 마이그레이션을 랩핑한다. 데이터베이스가 이를 지원하지 않으면 마이그레이션이 실패 할 때 일부 성공한 부분이 롤백되지 않는다. 이 부분에 대해서는 별도의 롤백 작업을 해야 한다.</p><div class="note"><p>트랜잭션 내에서 실행할 수 없는 특정 쿼리가 있다. 어댑터가 DDL 트랜잭션을 지원하는 경우 <code>disable_ddl_transaction!</code>을 사용하여 단일 마이그레이션에 대해 트랜잭선을 비활성화 할 수 있다.</p></div><p>액티브 레코드가 되돌릴 수 있는 방법을 모르는 작업을 수행하려면 <code>reversible</code> 메소드를 사용할 수 있다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class ChangeProductsPrice < ActiveRecord::Migration[5.0]
def change
reversible do |dir|
change_table :products do |t|
dir.up { t.change :price, :string }
dir.down { t.change :price, :integer }
end
end
end
end
</pre>
</div>
<p>또는 <code>change</code> 대신 <code>up</code>과 <code>down</code>을 사용할 수 있다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class ChangeProductsPrice < ActiveRecord::Migration[5.0]
def up
change_table :products do |t|
t.change :price, :string
end
end
def down
change_table :products do |t|
t.change :price, :integer
end
end
end
</pre>
</div>
<h3 id="creating-a-migration"><a class="anchorlink" href="#creating-a-migration">2 마이그레이션 작성하기</a></h3><h4 id="creating-a-standalone-migration"><a class="anchorlink" href="#creating-a-standalone-migration">2.1 별도의 마이그레이션 파일 작성하기</a></h4><p>마이그레이션은 각 마이그레이션 클래스마다 하나씩 <code>db/migrate</code> 디렉토리에 파일로 저장된다. 파일 이름은 <code>YYYYMMDDHHMMSS_create_products.rb</code> 형식을 가진다. 즉, 마이그레이션을 식별하는 UTC 타임 스탬프와 밑줄 그리고 마이그레이션 이름으로 구성되어 있다. 마이그레이션 클래스의 이름 (CamelCased 버전)은 파일 이름의 후반 부분과 일치해야 한다. 예를 들어<code>20080906120000_create_products.rb</code>는 <code>CreateProducts</code> 클래스를 정의하고 <code>20080906120001_add_details_to_products.rb</code>는<code>AddDetailsToProducts</code>를 정의해야 한다. 레일스는 이 타임 스탬프를 사용하여 마이그레이션을 어떤 순서로 실행할지 결정하므로 다른 애플리케이션에서 마이그레이션을 복사하거나 파일을 직접 생성하는 경우 순서에 따라 위치를 알고 있어야 한다.</p><p>물론 타임 스탬프 계산은 재미있는 작업이 아니기 때문에 액티브 레코드에서는 아래와 같은 작업을 처리 할 수 있는 생성자를 제공한다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration AddPartNumberToProducts
</pre>
</div>
<p>적절한 이름의 빈 마이그레이션이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
end
end
</pre>
</div>
<p>이 생성자는 파일 이름에 타임 스탬프를 추가하는 것 이상을 수행 할 수 있다. 명명 규칙 및 추가 (선택적) 인수를 기반으로 마이그레이션의 불필요한 부분을 제거할 수 있다.</p><p>마이그레이션 이름이 "AddColumnToTable" 또는 "RemoveColumnFromTable" 형식이고 컬럼의 이름과 데이터형 리스트가 오는 경우 적절한 <code>add_column</code>과 <code>remove_column</code> 문이 포함된 마이그레이션이 작성될 것이다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration AddPartNumberToProducts part_number:string
</pre>
</div>
<p>위와 같은 마이그레이션 명령으로 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string
end
end
</pre>
</div>
<p>새 컬럼에 인덱스를 추가하려면 아래와 같이 수행한다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration AddPartNumberToProducts part_number:string:index
</pre>
</div>
<p>실행결과 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddPartNumberToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string
add_index :products, :part_number
end
end
</pre>
</div>
<p>마찬가지로 커맨드라인에서 특정 컬럼을 제거하기 위해 마이그레이션을 생성할 수 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration RemovePartNumberFromProducts part_number:string
</pre>
</div>
<p>실행결과 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class RemovePartNumberFromProducts < ActiveRecord::Migration[5.0]
def change
remove_column :products, :part_number, :string
end
end
</pre>
</div>
<p>하나의 컬럼만 제한되지 않는다. 예를 들면 아래와 같이 두개의 컬럼을 추가할 수 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration AddDetailsToProducts part_number:string price:decimal
</pre>
</div>
<p>실행결과 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddDetailsToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :part_number, :string
add_column :products, :price, :decimal
end
end
</pre>
</div>
<p>마이그레이션 이름이 "CreateXXX" 형식이고 컬럼 이름 및 데이터형 리스트가 뒤따라 오면 행달 컬럼들이 포함된 테이블 XXX를 작성하는 마이그레이션이 생성될 것이다. 예를 들면,</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration CreateProducts name:string part_number:string
</pre>
</div>
<p>실행결과 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class CreateProducts < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.string :name
t.string :part_number
end
end
end
</pre>
</div>
<p>항상 그렇듯이 이렇게 생성된 것은 시작에 불과하다. <code>db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rb</code> 파일을 편집하여 원하는 대로 추가하거나 제거 할 수 있다.</p><p>또한 생성자는 컬럼 데이터형으로 <code>references</code>(또는 <code>belongs_to</code>)을 사용할 수 있다. 예를 들면,</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration AddUserRefToProducts user:references
</pre>
</div>
<p>실행결과 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddUserRefToProducts < ActiveRecord::Migration[5.0]
def change
add_reference :products, :user, foreign_key: true
end
end
</pre>
</div>
<p>이 마이그레이션은 <code>user_id</code> 컬럼과 적절한 인덱스를 생성할 것이다 .
<code>add_reference</code> 옵션에 대한 자세한 내용을 보기 위해서는 <a href="https://api.rubyonrails.org/6-0-stable/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference">API documentation</a>을 방문한다.</p><p>이름의 일부 중 <code>JoinTable</code>이 포함되어 있는 경우 조인 테이블을 생성하는 생성자도 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails g migration CreateJoinTableCustomerProduct customer product
</pre>
</div>
<p>실행결과 아래와 같은 마이그레이션 클래스 파일이 생성될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class CreateJoinTableCustomerProduct < ActiveRecord::Migration[5.0]
def change
create_join_table :customers, :products do |t|
# t.index [:customer_id, :product_id]
# t.index [:product_id, :customer_id]
end
end
end
</pre>
</div>
<h4 id="model-generators"><a class="anchorlink" href="#model-generators">2.2 모델 생성자</a></h4><p>모델 및 스카폴드 생성자는 새 모델 추가에 적합한 마이그레이션을 작성한다. 이 마이그레이션에는 관련 테이블 작성에 대한 지시 사항이 이미 포함되어 있다. 원하는 컬럼을 레일스에 알려 주면 이 컬럼을 추가하기 위한 명령문도 작성된다. 예를 들어 아래의 명령를 실행하면,</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate model Product name:string description:text
</pre>
</div>
<p>아래와 같은 마이그레이션 클래스를 생성할 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class CreateProducts < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
</pre>
</div>
<p>원하는 만큼 컬럼 이름/데이터형 쌍을 추가 할 수 있다.</p><h4 id="passing-modifiers"><a class="anchorlink" href="#passing-modifiers">2.3 데이터형 변경자 지정하기</a></h4><p>일반적으로 사용되는 몇몇 <a href="#column-modifiers">데이터형 변경자</a>는 커맨드 라인에서 직접 지정할 수 있다. 중괄호로 묶고 필드 데이터형 다음에 지정한다.</p><p>예를 들어 아래와 같이 실행하면</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails generate migration AddDetailsToProducts 'price:decimal{5,2}' supplier:references{polymorphic}
</pre>
</div>
<p>아래와 같은 마이그레이션 클래스 파일을 생성할 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddDetailsToProducts < ActiveRecord::Migration[5.0]
def change
add_column :products, :price, :decimal, precision: 5, scale: 2
add_reference :products, :supplier, polymorphic: true
end
end
</pre>
</div>
<div class="info"><p>자세한 내용은 생성자 도움말을 살펴 보기 바란다.</p></div><h3 id="writing-a-migration"><a class="anchorlink" href="#writing-a-migration">3 마이그레이션 작성하기</a></h3><p>생성자 중 하나를 사용하여 마이그레이션을 생성했다면 이제는 작업해야 할 때다.</p><h4 id="creating-a-table"><a class="anchorlink" href="#creating-a-table">3.1 테이블 생성하기</a></h4><p><code>create_table</code> 메소드는 가장 기본적인 방법 중 하나이지만 대부분의 경우 모델 또는 스카폴드 생성자를 사용할 때 생성된다. 일반적인 용도는 아래와 같다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
create_table :products do |t|
t.string :name
end
</pre>
</div>
<p>위의 메소드는 <code>name</code>이라는 컬럼이 있는 <code>products</code> 테이블을 생성한다(아래에서 설명하는 것처럼, <code>id</code> 컬럼도 암묵적으로 자동 생성된다).</p><p>기본적으로 <code>create_table</code>은 <code>id</code>라는 기본키를 생성한다. <code>:primary_key</code> 옵션을 사용하여 기본키 이름을 변경하거나 (이 경우, 해당 모델을 업데이트하는 것을 잊지 말아야 한다.) 기본키를 원하지 않으면 <code>id: false</code> 옵션을 전달할 수 있다. 데이터베이스 특정 옵션을 전달해야 하는 경우 <code>:options</code> 옵션에 SQL문 일부를 지정할 수 있다. 예를 들어,</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
create_table :products, options: "ENGINE=BLACKHOLE" do |t|
t.string :name, null: false
end
</pre>
</div>
<p>위의 코드는 테이블을 생성하는데 사용되는 SQL 문에 <code>ENGINE=BLACKHOLE</code> 옵션이 추가될 것이다.</p><p>또한 테이블에 대한 설명을 <code>:comment</code> 옵션으로 전달하여 데이터베이스 자체에 저장할 수 있고 MySQL Workbench 또는 PgAdmin III과 같은 데이터베이스 관리 도구로 볼 수 있다. 데이터 모델을 이해하고 문서를 생성하는 데 도움이 될 수 있으므로 규모가 큰 데이터베이스와 연결되는 애플리케이션에 사용하는 마이그레이션에는 주석을 지정하는 것이 좋다. 현재로는 MySQL 및 PostgreSQL 어댑터 만 주석을 지원한다.</p><h4 id="creating-a-join-table"><a class="anchorlink" href="#creating-a-join-table">3.2 조인 테이블 생성하기</a></h4><p>마이그레이션 메소드인 <code>create_join_table</code>은 HABTM(has and belongs to
many) 조인 테이블을 생성한다. 일반적인 사용법 아래와 같다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
create_join_table :products, :categories
</pre>
</div>
<p><code>category_id</code>와<code>product_id</code>라는 두 개의 컬럼이 있는 <code>categories_products</code> 테이블을 만든다. 이 컬럼에는 기본적으로 <code>:null</code> 옵션이 <code>false</code>로 설정되어 있다. <code>:column_options</code> 옵션을 지정하여 덮어 쓸 수 있다 .</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
create_join_table :products, :categories, column_options: { null: true }
</pre>
</div>
<p>기본적으로, 조인 테이블의 이름은 알파벳 순서로 create_join_table에 제공된 처음 두 인수를 합쳐서 만들어진다. 테이블 이름을 사용자 정의하려면 <code>:table_name</code> 옵션을 지정하면 된다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
create_join_table :products, :categories, table_name: :categorization
</pre>
</div>
<p>위의 명령을 실행하면 <code>categorization</code> 테이블이 생성된다.</p><p><code>create_join_table</code>은 (기본적으로 생성되지 않은) 인덱스 또는 컬럼을 추가하는 데 사용할 수 있는 블록도 허용한다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
create_join_table :products, :categories do |t|
t.index :product_id
t.index :category_id
end
</pre>
</div>
<h4 id="changing-tables"><a class="anchorlink" href="#changing-tables">3.3 테이블 변경하기</a></h4><p><code>create_table</code>의 가까운 사촌은 <code>change_table</code>이며 기존 테이블을 변경하는 데 사용된다. <code>create_table</code>과 비슷한 방식으로 사용 되지만 블록 변수로 넘겨지는 객체는 더 많은 마술 같은 능력을 가진다. 예를 들면 아래와 같다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
change_table :products do |t|
t.remove :description, :name
t.string :part_number
t.index :part_number
t.rename :upccode, :upc_code
end
</pre>
</div>
<p>위의 코드는 <code>description</code> 및<code>name</code> 컬럼을 제거하고 <code>part_number</code> 문자열 컬럼을 작성하고 인덱스를 추가한다. 마지막으로 <code>upccode</code> 컬럼의 이름을 변경한다.</p><h4 id="changing-columns"><a class="anchorlink" href="#changing-columns">3.4 컬럼 변경하기</a></h4><p><code>remove_column</code> 및 <code>add_column</code>과 같이 레일스는<code>change_column</code> 마이그레이션 메소드를 제공한다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
change_column :products, :part_number, :text
</pre>
</div>
<p>위의 코드를 실행하면 products 테이블의 <code>part_number</code> 컬럼이 <code>:text</code> 필드로 변경된다. <code>change_column</code> 명령은 되돌릴 수 없다는 것에 주목해야 한다.</p><p><code>change_column</code> 외에도 <code>change_column_null</code> 및<code>change_column_default</code> 메소드는 not null 제한 조건과 컬럼의 기본값을 변경하는 데 사용된다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
change_column_null :products, :name, false
change_column_default :products, :approved, from: true, to: false
</pre>
</div>
<p>위의 코드를 실행하면 products 테이블의 <code>:name</code> 필드를 <code>NOT NULL</code> 컬럼으로 설정하고 <code>:approved</code> 필드의 기본값을 true에서 false로 설정한다.</p><div class="note"><p>위의 <code>change_column_default</code> 마이그레이션을 <code>change_column_default :products, :approved, false</code>로 작성할 수도 있지만 이전 예제와 달리 마이그레이션을 되돌릴 수 없게 만든다.</p></div><h4 id="column-modifiers"><a class="anchorlink" href="#column-modifiers">3.5 컬럼 변경자</a></h4><p>컬럼을 만들거나 변경할 때 컬럼 변경자를 적용 할 수 있다.</p>
<ul>
<li>
<code>limit</code> : <code>string/text/binary/integer</code> 필드의 최대 크기를 설정한다.</li>
<li>
<code>precision</code> : <code>decimal</code>(소수점) 필드의 정밀도를 지정하며 숫자의 총 자릿수를 표시한다.</li>
<li>
<code>scale</code> : 소수점 이하 자릿수를 표시하며 <code>decimal</code> 필드의 스케일을 정의한다.</li>
<li>
<code>polymorphic</code> : <code>belongs_to</code> 관계 설정을 위한 <code>type</code> 컬럼을 추가한다.</li>
<li>
<code>null</code> : 컬럼에서 <code>NULL</code> 값의 허용 여부를 지정한다.</li>
<li>
<code>default</code> : 컬럼에서 기본값을 설정할 수 있다. 동적 값 (예 : 날짜)을 사용할 경우 기본값은 처음 (즉, 마이그레이션이 적용된 날짜)에만 계산된다것에 주목한다.</li>
<li>
<code>comment</code> : 컬럼에 주석을 추가한다.</li>
</ul>
<p>일부 어댑터는 추가 옵션을 지원할 수 있다. 자세한 정보는 어댑터 별 API 문서를 참조한다.</p><div class="note"><p><code>null</code> 및 <code>default</code>는 커맨드 라인을 통해 지정할 수 없다.</p></div><h4 id="foreign-keys"><a class="anchorlink" href="#foreign-keys">3.6 외래키</a></h4><p>필수 사항은 아니지만, <a href="#active-record-and-referential-integrity">guarantee referential integrity</a>에 외래키 제약 조건을 추가할 수 있다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
add_foreign_key :articles, :authors
</pre>
</div>
<p>이로써 <code>articles</code> 테이블의<code>author_id</code> 컬럼에 새로운 외래키가 추가됐다. 이 외래키는 <code>authors</code> 테이블의 <code>id</code> 컬럼을 참조한다. 컬럼 이름을 테이블 이름에서 유추할 수 없는 경우 <code>:column</code> 및 <code>:primary_key</code> 옵션을 사용한다.</p><p>레일스가 생성하는 모든 외래키는 <code>fk_rails</code>로 시작해서 <code>from_table</code>과 <code>column</code>으로부터 만들어지는 10개의 글자가 추가되어 생성하게 된다. 필요할 경우 다른 이름을 지정할 수 있는 <code>:name</code> 옵션이 있다.</p><div class="note"><p>액티브 레코드는 단일 컬럼 외래키만 지원한다. 복합 외래키를 사용하려면 <code>execute</code> 및 <code>structure.sql</code>이 필요하다. <a href="#schema-dumping-and-you">Schema Dumping and You</a>를 참조한다.
외래키를 제거하는 것도 간단하다.</p></div><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# 액티브 레코드가 컬럼 이름을 알아 내게 한다.
remove_foreign_key :accounts, :branches
# 특정 컬럼에 대한 외래키를 제거한다.
remove_foreign_key :accounts, column: :owner_id
# 이름을 지정하여 외래키를 제거한다.
remove_foreign_key :accounts, name: :special_fk_name
</pre>
</div>
<h4 id="when-helpers-aren't-enough"><a class="anchorlink" href="#when-helpers-aren" t-enough>3.7 헬퍼 메소드가 충분히 않을 때</a></h4><p>액티브 레코드에서 제공하는 헬퍼가 충분하지 않으면 <code>execute</code> 메소드를 사용하여 임의의 SQL을 실행할 수 있다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
Product.connection.execute("UPDATE products SET price = 'free' WHERE 1=1")
</pre>
</div>
<p>개별 메소드의 세부 사항 및 예제는 API 문서를 확인한다.
특히, <a href="https://api.rubyonrails.org/6-0-stable/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html"><code>ActiveRecord::ConnectionAdapters::SchemaStatements</code></a> ( <code>change</code>, <code>up</code>, <code>down</code> 메소드에서 사용할 수 있는 메소드를 제공하는 문서), <a href="https://api.rubyonrails.org/6-0-stable/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html"><code>ActiveRecord::ConnectionAdapters::TableDefinition</code></a> (<code>create_table</code>에 의해 생성된 객체에서 사용 가능한 메소드를 제공하는 문서) 그리고 <a href="https://api.rubyonrails.org/6-0-stable/classes/ActiveRecord/ConnectionAdapters/Table.html"><code>ActiveRecord::ConnectionAdapters::Table</code></a> (<code>change_table</code>에 의해 생성 된 객체에서 사용 가능한 메소드를 제공하는 문서) 등이다.</p><h4 id="using-the-change-method"><a class="anchorlink" href="#using-the-change-method">3.8 <code>change</code> 메소드 사용하기</a></h4><p><code>change</code> 메소드는 마이그레이션을 작성하는 주된 방법이다. 액티브 레코드가 마이그레이션을 자동으로 되돌리는 방법을 알고 있는 경우에만 대부분 작동한다. 현재 <code>change</code> 메소드는 아래의 마이그레이션 정의만 지원한다.</p>
<ul>
<li>add_column</li>
<li>add_foreign_key</li>
<li>add_index</li>
<li>add_reference</li>
<li>add_timestamps</li>
<li>change_column_default (:from 과 :to 옵션을 지정해야 함.)</li>
<li>change_column_null</li>
<li>create_join_table</li>
<li>create_table</li>
<li>disable_extension</li>
<li>drop_join_table</li>
<li>drop_table (블록을 지정해야 함.)</li>
<li>enable_extension</li>
<li>remove_column (데이터형을 지정해야 함.)</li>
<li>remove_foreign_key (두번째 테이블을 지정해야 함.)</li>
<li>remove_index</li>
<li>remove_reference</li>
<li>remove_timestamps</li>
<li>rename_column</li>
<li>rename_index</li>
<li>rename_table</li>
</ul>
<p><code>change_table</code>은 블록이 <code>change</code>, <code>change_default</code> 또는<code>remove</code>를 호출하지 않는 한 가역적이다.</p><p><code>remove_column</code>은 컬럼 데이터형을 세 번째 인수로 제공하면 되돌릴 수 있다. 원본의 컬럼 옵션도 제공하도록 한다. 그렇지 않으면 레일스가 롤백 할 때 컬럼을 정확하게 다시 생성할 수 없다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
remove_column :posts, :slug, :string, null: false, default: ''
</pre>
</div>
<p>다른 메소드를 사용해야 할 경우에는 <code>change</code> 대신 <code>reversible</code> 메소드를 사용하거나 <code>up</code> 과 <code>down</code> 메소드를 작성해야 한다.</p><h4 id="using-reversible"><a class="anchorlink" href="#using-reversible">3.9 <code>reversible</code> 메소드 사용하기</a></h4><p>복잡한 마이그레이션에서는 액티브 레코드가 되돌릴 방법을 모르는 경우를 처리해야 할 필요가 있다. <code>reversible</code> 메소드를 사용하여 마이그레이션을 실행할 때 수행할 작업과 되돌릴 때 수행할 작업을 지정할 수 있다. 예를 들면 아래와 같다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class ExampleMigration < ActiveRecord::Migration[5.0]
def change
create_table :distributors do |t|
t.string :zipcode
end
reversible do |dir|
dir.up do
# add a CHECK constraint
execute <<-SQL
ALTER TABLE distributors
ADD CONSTRAINT zipchk
CHECK (char_length(zipcode) = 5) NO INHERIT;
SQL
end
dir.down do
execute <<-SQL
ALTER TABLE distributors
DROP CONSTRAINT zipchk
SQL
end
end
add_column :users, :home_page_url, :string
rename_column :users, :email, :email_address
end
end
</pre>
</div>
<p><code>reversible</code> 메소드를 사용할 때 명령도 올바른 순서로 실행되어야 한다. 이전 예제 마이그레이션을 되돌릴 경우 <code>home_page_url</code> 컬럼이 제거 된 후 <code>distributors</code> 테이블이 삭제되기 직전에 <code>down</code> 블록이 실행될 것이다.</p><p>때때로 마이그레이션은 돌이킬 수 없는 단순한 일을 할 것이다. 예를 들어 일부 데이터를 손상시킬 수도 있다. 이 경우 <code>down</code> 블록에서 <code>ActiveRecord::IrreversibleMigration</code> 예외를 발생시킬 수 있다. 누군가 마이그레이션을 되돌리려고 하면 수행 할 수 없다는 오류 메시지가 표시될 것이다.</p><h4 id="using-the-up/down-methods"><a class="anchorlink" href="#using-the-up/down-methods">3.10 <code>up</code>/<code>down</code> 메소드 사용하기</a></h4><p><code>change</code> 메소드 대신 <code>up</code> 및 <code>down</code> 메소드를 사용하여 이전 스타일의 마이그레이션을 사용할 수도 있다.
<code>up</code> 메소드는 스키마에 적용할 변환내용을 기술해야 하며, 마이그레이션의<code>down</code> 메소드는 <code>up</code> 메소드가 수행한 변환을 되돌려야 한다. 즉, <code>up</code> 다음에<code>down</code>을 수행하면 데이터베이스 스키마는 변경되지 않아야 한다. 예를 들어, <code>up</code> 메소드에서 테이블을 작성하는 경우 <code>down</code> 메소드에서 테이블을 삭제해야한다. <code>up</code> 메소드로 만들어진 역순으로 변환을 수행하는 것이 현명하다. 아래의 예는 <code>reversible</code> 섹션에 있는 것과 동일한 내용이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class ExampleMigration < ActiveRecord::Migration[5.0]
def up
create_table :distributors do |t|
t.string :zipcode
end
# add a CHECK constraint
execute <<-SQL
ALTER TABLE distributors
ADD CONSTRAINT zipchk
CHECK (char_length(zipcode) = 5);
SQL
add_column :users, :home_page_url, :string
rename_column :users, :email, :email_address
end
def down
rename_column :users, :email_address, :email
remove_column :users, :home_page_url
execute <<-SQL
ALTER TABLE distributors
DROP CONSTRAINT zipchk
SQL
drop_table :distributors
end
end
</pre>
</div>
<p>마이그레이션이 되돌릴 수 없는 경우 <code>down</code> 메소드에서 <code>ActiveRecord::IrreversibleMigration</code> 예외를 발생시켜야 한다. 누군가 마이그레이션을 되돌리려고 하면 이를 수행 할 수 없다는 오류 메시지가 표시될 것이다.</p><h4 id="reverting-previous-migrations"><a class="anchorlink" href="#reverting-previous-migrations">3.11 이전 마이그레이션 되돌리기</a></h4><p><code>revert</code> 메소드를 사용하여 액티브 레코드의 마이그레이션 롤백 기능을 사용할 수 있다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
require_relative '20121212123456_example_migration'
class FixupExampleMigration < ActiveRecord::Migration[5.0]
def change
revert ExampleMigration
create_table(:apples) do |t|
t.string :variety
end
end
end
</pre>
</div>
<p>또한, <code>revert</code> 메소드는 되돌리기 위한 명령을 블록으로 받을 수 있다. 이것은 이전 마이그레이션에서 특정 부분을 되돌리는 데 유용 할 수 있다. 예를 들어, 이미 <code>ExampleMigration</code>을 커밋한 상황을 가정한다면, 'CHECK' 제약 조건 대신 액티브 레코드 유효성 검사를 사용하여 우편 번호를 확인하는 것이 가장 좋은 방법이 될 것이다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class DontUseConstraintForZipcodeValidationMigration < ActiveRecord::Migration[5.0]
def change
revert do
# copy-pasted code from ExampleMigration
reversible do |dir|
dir.up do
# add a CHECK constraint
execute <<-SQL
ALTER TABLE distributors
ADD CONSTRAINT zipchk
CHECK (char_length(zipcode) = 5);
SQL
end
dir.down do
execute <<-SQL
ALTER TABLE distributors
DROP CONSTRAINT zipchk
SQL
end
end
# The rest of the migration was ok
end
end
end
</pre>
</div>
<p><code>revert</code>를 사용하지 않고 동일한 마이그레이션을 작성할 수도 있겠지만 몇 가지 단계가 더 필요할 것이다. 즉, <code>create_table</code>과 <code>reversible</code> 순서를 바꾸고, <code>create_table</code>을 <code>drop_table</code>로 변경하며, 마지막으로 <code>up</code>을 <code>down</code>으로 대체하는 것이다. 이 반대로도 마찬가지다. 이것은 모두 <code>revert</code> 메소드에 의해 처리된다.</p><p>위의 예와 같이 check 제약 조건을 추가하려면 <code>structure.sql</code>을 덤프 메소드로 사용해야 한다. <a href="#schema-dumping-and-you">Schema Dumping and You</a>를 참조하기 바란다.</p><h3 id="running-migrations"><a class="anchorlink" href="#running-migrations">4 마이그레이션 실행하기</a></h3><p>레일스는 마이그레이션 작업을 실행하기 위해 몇가지 rails 명령을 제공한다.</p><p>가장 먼저 사용할 마이그레이션 관련 rails 명령은 아마도 <code>rails db:migrate</code> 일 것이다. 가장 기본적인 형태로는, 아직 실행되지 않은 모든 마이그레이션에 대해 <code>change</code> 또는<code>up</code> 메소드만을 실행하는 것이다. 이와 같이 미실행 마이그레이션이 없으면 작업은 바로 종료된다. 이러한 마이그레이션 작업은 마이그레이션 날짜를 기준으로 순서대로 실행된다.</p><p><code>db:migrate</code> 명령을 실행하면 <code>db:schema:dump</code> 명령이 호출되어 데이터베이스의 구조와 일치하도록 <code>db/schema.rb</code> 파일이 업데이트된다는 것을 주목한다.</p><p>대상 버전을 지정하면 액티브 레코드는 지정된 버전에 도달 할 때까지 필요한 마이그레이션(change, up, down)을 실행한다. 버전은 마이그레이션 파일 이름의 숫자 접두사에 해당한다. 예를 들어, 20080906120000 버전으로 마이그레이션하려면 아래와 같이 실행한다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails db:migrate VERSION=20080906120000
</pre>
</div>
<p>20080906120000 버전이 현재 버전보다 큰 경우 (즉, 위로 마이그레이션하는 경우) 20080906120000 이하의 모든 마이그레이션에서 <code>change</code> (또는 <code>up</code>) 메소드를 실행하며 이후 마이그레이션은 실행되지 않는다. 아래쪽으로 마이그레이션하는 경우 20080906120000 이전까지(포함하지 않음)의 모든 마이그레이션에서 <code>down</code> 메소드가 실행된다.</p><h4 id="rolling-back"><a class="anchorlink" href="#rolling-back">4.1 롤백하기</a></h4><p>일반적인 작업으로는 마지막 마이그레이션을 롤백하는 것이다. 예를 들어, 마이그레이션 코딩에 오류가 있어 정정하려는 경우다. 이 경우에는 이전 마이그레이션과 관련된 버전 번호를 추적할 필요없이 아래와 같이 실행할 수 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails db:rollback
</pre>
</div>
<p>이로써 <code>change</code> 메소드를 되돌리거나 <code>down</code> 메소드를 실행하여 최신 마이그레이션을 롤백한다. 여러 마이그레이션을 취소해야하는 경우는 <code>STEP</code> 매개 변수를 사용할 수 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails db:rollback STEP=3
</pre>
</div>
<p>위의 명령은 마지만 3개의 마이그레이션을 되돌릴 것이다.</p><p><code>db:migrate:redo</code> 명령은 롤백을 수행 한 후 다시 마이그레이션하기 위한 손쉬운 방법이다. <code>db:rollback</code> 명령과 마찬가지로, 하나 이상의 버전으로 되돌아가야 하는 경우 <code>STEP</code> 옵션을 사용할 수 있다. 예를 들면 아래와 같다. </p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails db:migrate:redo STEP=3
</pre>
</div>
<p>이와 같은 rails 명령은 <code>db:migrate</code>로 할 수 있는 모든 작업을 할 수 있다. 마이그레이션할 버전을 명시적으로 지정할 필요가 없기 때문에 더 편리하다.</p><h4 id="setup-the-database"><a class="anchorlink" href="#setup-the-database">4.2 데이터베이스 셋업하기</a></h4><p><code>rails db:setup</code> 명령은 데이터베이스를 생성하고 스키마를 로드한 후 시드(seed) 데이터로 초기화 한다.</p><h4 id="resetting-the-database"><a class="anchorlink" href="#resetting-the-database">4.3 데이터베이스 재설정(reset)하기</a></h4><p><code>rails db:reset</code> 명령은 데이터베이스를 삭제하고 다시 셋업한다. 이것은 <code>rails db:drop db:setup</code>과 기능상 동일하다.</p><div class="note"><p>이것은 모든 마이그레이션을 실행하는 것과 다르다. 이 명령은 현재 상태의 <code>db/schema.rb</code> 또는 <code>db/structure.sql</code> 파일의 내용만 사용한다. 마이그레이션을 롤백 할 수 없으면 <code>rails db:reset</code>이 도움이 되지 않을 수 있다. 스키마 덤프에 대한 자세한 내용은 <a href="#schema-dumping-and-you">Schema Dumping and You</a> 섹션을 참조한다.</p></div><h4 id="running-specific-migrations"><a class="anchorlink" href="#running-specific-migrations">4.4 특정 마이그레이션 실행하기</a></h4><p>특정 마이그레이션 up 또는 down을 실행해야 하는 경우 <code>db:migrate:up</code> 및 <code>db:migrate:down</code> 명령을 사용한다. 적절한 버전을 지정하면 해당 마이그레이션에 <code>change</code>,<code>up</code> 또는 <code>down</code> 메소드가 호출된다. 예를 들면 아래와 같다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails db:migrate:up VERSION=20080906120000
</pre>
</div>
<p>위의 명령을 실행하면 <code>change</code> 메소드 (또는 <code>up</code> 메소드)를 실행하여 20080906120000 마이그레이션을 실행할 것이다. 이 명령은 먼저 마이그레이션이 이미 수행되었는지 확인하고 액티브 레코드가 이미 실행 된 것으로 판단되면 아무 작업도 수행하지 않는다.</p><h4 id="running-migrations-in-different-environments"><a class="anchorlink" href="#running-migrations-in-different-environments">4.5 환경별로 마이그레이션 실행하기</a></h4><p>기본적으로 <code>rails db:migrate</code>를 실행하면 <code>development</code> 환경에서 실행된다. 다른 환경에 대해 마이그레이션을 실행하려면 명령을 실행하는 동안<code>RAILS_ENV</code> 환경 변수를 사용하여 마이그레이션을 지정할 수 있다. 예를 들어<code>test</code> 환경에 대해 마이그레이션을 실행하려면 아래와 같이 실행할 수 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
$ rails db:migrate RAILS_ENV=test
</pre>
</div>
<h4 id="changing-the-output-of-running-migrations"><a class="anchorlink" href="#changing-the-output-of-running-migrations">4.6 마이그레이션 실행 결과 변경하기</a></h4><p>기본적으로 마이그레이션은 수행 중인 작업과 소요 시간을 정확하게 알려 준다. 테이블을 작성하고 인덱스를 추가하는 마이그레이션은 아래와 같은 결과를 생성할 수 있다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
== CreateProducts: migrating =================================================
-- create_table(:products)
-> 0.0028s
== CreateProducts: migrated (0.0028s) ========================================
</pre>
</div>
<p>이 모든 것을 제어 할 수 있는 몇 가지 메소드를 마이그레이션에서 사용할 수 있다.</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td>suppress_messages</td>
<td>블록을 인수로 사용하고 블록에서 생성 된 출력을 보이지 않도록 한다.</td>
</tr>
<tr>
<td>say</td>
<td>메시지 인수를 받아서 그대로 출력한다. 들여 쓰기 여부를 지정하기 위해 두 번째 논리값 인수를 전달할 수 있다.</td>
</tr>
<tr>
<td>say_with_time</td>
<td>블록을 실행하는 데 걸린 시간과 함께 텍스트를 출력한다. 블록이 정수를 반환하면 영향을 받는 레코드 갯수로 가정한다.</td>
</tr>
</tbody>
</table>
<p>예를 들어, 아래의 마이그레이션 작업은 </p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class CreateProducts < ActiveRecord::Migration[5.0]
def change
suppress_messages do
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
say "Created a table"
suppress_messages {add_index :products, :name}
say "and an index!", true
say_with_time 'Waiting for a while' do
sleep 10
250
end
end
end
</pre>
</div>
<p>아래와 같은 결과를 보일 것이다.</p><div class="code_container">
<pre class="brush: plain; gutter: false; toolbar: false">
== CreateProducts: migrating =================================================
-- Created a table
-> and an index!
-- Waiting for a while
-> 10.0013s
-> 250 rows
== CreateProducts: migrated (10.0054s) =======================================
</pre>
</div>
<p>액티브 레코드가 아무 것도 출력하지 않게 하려면, <code>rails db:migrate VERBOSE=false</code>를 실행하면 모든 출력이 보이지 않게 된다.</p><h3 id="changing-existing-migrations"><a class="anchorlink" href="#changing-existing-migrations">5 기존 마이그레이션 변경하기</a></h3><p>때때로 마이그레이션을 작성할 때 실수를 할 수 있다. 이미 마이그레이션을 실행했다면, 마이그레이션을 편집하고 마이그레이션을 다시 실행할 수 없다. 레일스는 마이그레이션이 이미 실행 된 것으로 생각하고 <code>rails db:migrate</code>를 실행할 때 아무런 작업도 하지 않는다. 마이그레이션을 롤백 (예 : <code>rails db:rollback</code>)하고 마이그레이션을 편집한 다음 <code>rails db:migrate</code>를 실행하여 수정된 버전을 실행한다.</p><p>일반적으로 기존 마이그레이션을 변경하는 것은 좋지 않다. 기존 버전의 마이그레이션이 이미 운영 시스템에서 실행된 경우 자신과 동료를 위해 추가 작업을 작성하면 심각한 문제를 유발할 수 있다. 대신 필요한 작업을 변경하는 새 마이그레이션을 작성해야 한다. 아직 소스 컨트롤(SCM)(또는 일반적으로 개발 시스템을 넘어 전파되지 않은 경우)에 커밋하지 않은 새로 생성된 마이그레이션을 편집하는 것은 상대적으로 무해하다.</p><p><code>revert</code> 메소드는 이전 마이그레이션 전체 또는 일부를 취소하기 위해 새 마이그레이션을 작성할 때 유용 할 수 있다(위의 <a href="#reverting-previous-migrations">Reverting Previous Migrations</a> 참조).</p><h3 id="schema-dumping-and-you"><a class="anchorlink" href="#schema-dumping-and-you">6 스키마 덤핑과 개발자</a></h3><h4 id="what-are-schema-files-for?"><a class="anchorlink" href="#what-are-schema-files-for?">6.1 스키마 파일의 목적</a></h4><p>마이그레이션이 강력하기는 하지만 데이터베이스 스키마의 신뢰할 수 있는 소스가 될 수는 없다. 데이터베이스는 신뢰할 수 있는 소스로서의 역할을 한다. 기본적으로 레일스는 데이터베이스 스키마의 현재 상태를 그대로 가져오는 <code>db/schema.rb</code>를 생성한다.</p><p>전체 마이그레이션 히스토리를 재생하는 것보다 <code>rails db:schema:load</code>를 통해 스키마 파일을 로드하여 애플리케이션 데이터베이스의 새 인스턴스를 작성하는 것이 더 빠르고 오류가 적은 경향이 있다. 변경될 수 있는 외부 의존성을 마이그레이션에서 사용하거나 마이그레이션과 별개로 발전되는 응용 프로그램 코드에 의존하는 경우 <a href="#old-migrations">이전의 오래된 마이그레이션</a>은 올바르게 적용되지 않을 수 있다.</p><p>스키마 파일은 액티브 레코드 객체의 속성을 빠르게 보고자 할 때도 유용하다. 이 정보는 모델 코드에 포함되어 있지 않고 여러 마이그레이션에 걸쳐 흩어져 있지만 스키마 파일에 잘 요약되어 있다.</p><h4 id="types-of-schema-dumps"><a class="anchorlink" href="#types-of-schema-dumps">6.2 스키마 덤프의 형식</a></h4><p>레일스가 생성한 스키마 덤프의 형식은 <code>config/application.rb</code>의<code>config.active_record.schema_format</code> 설정에 의해 조절된다. 기본적으로 형식은 <code>: ruby</code>이지만 <code>: sql</code>로 설정할 수도 있다.</p><p><code>:ruby</code>를 선택하면 스키마는 <code>db/schema.rb</code>에 저장된다. 이 파일을 보면 매우 큰 마이그레이션 코드와 매우 흡사하다는 것을 알 수 있다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
ActiveRecord::Schema.define(version: 2008_09_06_171750) do
create_table "authors", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "products", force: true do |t|
t.string "name"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
t.string "part_number"
end
end
</pre>
</div>
<p>여러면에서 이것은 바로 현재 상태 그대로를 반영하는 것이다. 이 파일은 데이터베이스를 조사한 후 <code>create_table</code>, <code>add_index</code> 등을 사용하여 구조를 표현함으로써 작성된다.</p><p><code>db/schema.rb</code>는 트리거, 시퀀스, 저장 프로시저, check 제약 조건 등과 같은 데이터베이스가 지원할 수 있는 모든 것을 표현할 수 없다. 마이그레이션시<code>execute</code>를 사용하여 루비 마이그레이션 DSL에서 지원하지 않는 데이터베이스 구조를 작성할 수 있지만, 스키마 덤퍼가 구문을 재구성하지 못할 수 있다. 이와 같은 기능을 사용하는 경우 새 데이터베이스 인스턴스를 만드는 데 유용한 정확한 스키마 파일을 얻으려면 스키마 형식을 <code>: sql</code>로 설정해야 한다.</p><p>스키마 형식이 <code>: sql</code>로 설정되면 해당 데이터베이스에서 제공하는 도구를 사용하여 데이터베이스 구조가 <code>db/structure.sql</code>로 덤프된다. 예를 들어 PostgreSQL의 경우<code>pg_dump</code> 유틸리티가 사용된다. MySQL과 MariaDB의 경우, 이 파일에는 다양한 테이블에 대한 <code>SHOW CREATE TABLE</code>의 출력이 포함될 것이다.</p><p><code>db/structure.sql</code>에서 스키마를 로드하려면 <code>rails db:structure:load</code>를 실행한다. 파일에 포함된 SQL 문을 실행하여 이 파일이 로드된다. 정의에 따라 데이터베이스 구조의 완벽한 복사본이 만들어진다.</p><h4 id="schema-dumps-and-source-control"><a class="anchorlink" href="#schema-dumps-and-source-control">6.3 스키마 덤프와 소스 컨트롤</a></h4><p>스키마 파일은 일반적으로 새 데이터베이스를 생성하는데 사용되므로 스키마 파일을 소스 컨트롤 하에 두는 것이 좋다.</p><p>두 개의 브랜치에서 각각 스키마를 수정한 후 머지할 경우 스키마 파일에서 병합 충돌이 발생할 수 있다. 이러한 충돌을 해결하려면 <code>rails db:migrate</code>를 실행하여 스키마 파일을 재생성하면 된다.</p><h3 id="active-record-and-referential-integrity"><a class="anchorlink" href="#active-record-and-referential-integrity">7 액티브 레코드와 참조 무결성</a></h3><p>액티브 레코드 방식에서는 논리적인 작업이 데이터베이스가 아닌 모델에 속한다고 주장한다. 따라서 일부 논리적인 작업을 데이터베이스로 가져오는 트리거 또는 제약 조건과 같은 기능은 그리 많이 사용되지는 않는다.</p><p><code>validates :foreign_key, uniqueness: true</code>와 같은 데이터 유효성 검증은 모델이 데이터 무결성을 강화할 수 있는 한 가지 방법이다. 관계 설정시 <code>:dependent</code> 옵션은 모델이 부모가 삭제될 때 자식 객체를 자동으로 삭제하도록 한다. 애플리케이션 수준에서 작동하는 것과 마찬가지로 이것도 참조 무결성을 보장할 수 없으므로 일부 사람들은 데이터베이스의 <a href="#foreign-keys">foreign key constraints</a>로 기능을 보강한다.</p><p>액티브 레코드는 이러한 기능을 직접 사용하기 위한 모든 도구를 제공하지는 않지만 <code>execute</code> 메소드를 사용하여 임의의 SQL을 실행할 수 있다.</p><h3 id="migrations-and-seed-data"><a class="anchorlink" href="#migrations-and-seed-data">8 마이그레이션과 시드 데이터</a></h3><p>레일스의 마이그레이션 기능의 주요 목적은 일관된 프로세스를 사용하여 스키마를 수정하는 명령을 실행하는 것이다. 마이그레이션을 사용하여 데이터를 추가하거나 수정할 수도 있다. 이것은 운영 데이터베이스와 같이 파괴하거나 다시 만들 수 없는 기존 데이터베이스에 유용하다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class AddInitialProducts < ActiveRecord::Migration[5.0]
def up
5.times do |i|
Product.create(name: "Product ##{i}", description: "A product.")
end
end
def down
Product.delete_all
end
end
</pre>
</div>
<p>데이터베이스 생성 후 초기 데이터를 추가하기 위해 레일스에는 프로세스를 빠르고 쉽게 만드는 '시드(seed)' 기능이 내장되어 있다. 개발 및 테스트 환경에서 데이터베이스를 자주 다시 로드 할 때 특히 유용하다. 이 기능을 시작하는 것은 쉽다. 즉, 루비 코드로 <code>db/seeds.rb</code> 파일을 채우고 <code>rails db:seed</code> 명령을 실행하면된다.</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
5.times do |i|
Product.create(name: "Product ##{i}", description: "A product.")
end
</pre>
</div>
<p>This is generally a much cleaner way to set up the database of a blank application.</p><h3 id="old-migrations"><a class="anchorlink" href="#old-migrations">9 과거 마이그레이션</a></h3><p><code>db/schema.rb</code> 또는 <code>db/structure.sql</code>은 데이터베이스의 현재 상태에 대한 스냅 샷이며 해당 데이터베이스를 재구축하기 위한 신뢰할 수 있는 소스이다. 과거 마이그레이션 파일을 삭제하는 것이 가능하다. </p><p><code>db/migrate/</code> 디렉토리에서 마이그레이션 파일을 삭제하면, 해당 파일이 존재하는 상태에서 <code>rails db:migrate</code>가 실행되었던 환경에는 내부 레일스 데이터베이스 테이블(<code>schema_migrations</code>) 내부에 해당 마이그레이션의 타임스탬프 참조가 포함된다. 이 테이블은 특정 환경에서 마이그레이션이 실행되었는지 여부를 추적하는 데 사용된다.</p><p>각 마이그레이션의 상태 (up 또는 down)를 표시하는 <code>rails db:migrate :status</code> 명령을 실행하면, 특정 환경에서 한 번 실행 되었지만 더 이상 <code>db/migrate/</code> 디렉토리에서 찾을 수 없는 삭제된 마이그레이션 파일 옆에 <code>********** NO FILE **********</code>이 표시된다.</p>
<h3>피드백</h3>
<p>
이 가이드의 품질을 향상시키기 위해 여러분의 도움이 필요하다.
</p>
<p>
오타나 실제 오류를 발견시 여러분의 기여를 권고한다. 시작하려면 본 <a href="https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#contributing-to-the-rails-documentation">가이드의 기여</a> 섹션을 읽어보기 바란다.
</p>
<p>
미완성된 컨텐츠나 업데이트되지 않은 내용을 발견할 수도 있다. 누락된 문서는 master 브랜치에 추가한다. 제시된 이슈들이 master 브랜치 상에서 이미 해결되었는지 여부를 확인하려면 먼저 <a href="https://edgeguides.rubyonrails.org">Edge Guides</a>를 확인한다. 스타일과 규칙에 대해서는 <a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails Guides Guidelines</a>을 확인한다.
</p>
<p>
어떤 이유로든 고칠 수 있지만 직접 패치 할 수 없는 경우 <a href="https://github.com/rails/rails/issues">이슈를 새로 오픈</a>하면 된다.
</p>
<p>
그리고 마지막으로, 루비온레일스 문서에 관한 모든 논의는 <a href="https://groups.google.com/forum/#!forum/rubyonrails-docs">rubyonrails-docs 메일링 리스트</a> 상에서 언제든지 가능하다.
</p>
</div>
</div>
</div>
<hr class="hide" />
<div id="footer">
<div class="wrapper">
<p>본 결과물은 <a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a> 를 준수한다. </p>
<p>"Rails", "Ruby on Rails", 그리고 레일스 로고는 David Heinemeier Hansson의 등록상표이다. 판권 소유.</p>
</div>
</div>
</body>
</html>