-
Notifications
You must be signed in to change notification settings - Fork 2
/
chapter1.html
1373 lines (1053 loc) · 104 KB
/
chapter1.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 lang="zh_CN">
<head>
<meta charset="utf-8" />
<title>第 1 章 从零到部署</title>
<meta name="author" content="Andor Chen" />
<link rel="stylesheet" href="assets/styles/style.css" />
<script type="text/javascript" src="http://cdn.staticfile.org/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="assets/js/global.js"></script>
</head>
<body>
<div class="wrapper">
<div class="header">
<h1 class="logo"><a class="ir" href="http://railstutorial-china.org/rails4">Ruby on Rails 教程</a></h1>
<p class="subtitle">Ruby on Rails Tutorial 原书第 2 版(涵盖 Rails 4)</p>
</div>
<div class="content">
<div class="item chapter">
<h1 id="chapter-1"><span>第 1 章</span> 从零到部署</h1>
<ol class="toc"> <li class="level-2">
<a href="#section-1-1">1.1 简介</a>
</li>
<li class="level-3">
<a href="#section-1-1-1">1.1.1 给不同读者群的建议</a>
</li>
<li class="level-3">
<a href="#section-1-1-2">1.1.2 Rails 的性能</a>
</li>
<li class="level-3">
<a href="#section-1-1-3">1.1.3 本书排版约定</a>
</li>
<li class="level-2">
<a href="#section-1-2">1.2 搭建环境</a>
</li>
<li class="level-3">
<a href="#section-1-2-1">1.2.1 开发环境</a>
</li>
<li class="level-3">
<a href="#section-1-2-2">1.2.2 安装 Ruby,RubyGems,Rails 和 Git</a>
</li>
<li class="level-3">
<a href="#section-1-2-3">1.2.3 第一个程序</a>
</li>
<li class="level-3">
<a href="#section-1-2-4">1.2.4 Bundler</a>
</li>
<li class="level-3">
<a href="#section-1-2-5">1.2.5 rails server</a>
</li>
<li class="level-3">
<a href="#section-1-2-6">1.2.6 模型-视图-控制器(MVC)</a>
</li>
<li class="level-2">
<a href="#section-1-3">1.3 用 git 做版本控制</a>
</li>
<li class="level-3">
<a href="#section-1-3-1">1.3.1 安装与设置</a>
</li>
<li class="level-3">
<a href="#section-1-3-2">1.3.2 添加文件并提交</a>
</li>
<li class="level-3">
<a href="#section-1-3-3">1.3.3 git 为我们带来了什么好处?</a>
</li>
<li class="level-3">
<a href="#section-1-3-4">1.3.4 GitHub</a>
</li>
<li class="level-3">
<a href="#section-1-3-5">1.3.5 分支,编辑,提交,合并</a>
</li>
<li class="level-2">
<a href="#section-1-4">1.4 部署</a>
</li>
<li class="level-3">
<a href="#section-1-4-1">1.4.1 搭建 Heroku 部署环境</a>
</li>
<li class="level-3">
<a href="#section-1-4-2">1.4.2 Heroku 部署第一步</a>
</li>
<li class="level-3">
<a href="#section-1-4-3">1.4.3 Heroku 部署第二步</a>
</li>
<li class="level-3">
<a href="#section-1-4-4">1.4.4 Heroku 的其他命令</a>
</li>
<li class="level-2">
<a href="#section-1-5">1.5 小结</a>
</li>
</ol>
<div class="main">
<p>欢迎学习《Ruby on Rails 教程》。本书的目标是成为对“如果想学习使用 Ruby on Rails 进行 Web 开发,我应该从哪儿开始?”这一问题的最好答案。学习完本书的内容之后,你将具备使用 Rails 进行开发和部署 Web 程序的技能。同时你还能够通过一些进阶的书籍、博客和视频教程等活跃的 Rails 教学体系继续深造。本书基于 Rails 4,这里的知识代表着 Web 开发的发展方向。(《Ruby on Rails 教程》的最新版本可以从<a href="http://railstutorial.org/">本书的网站</a>上获取。)</p>
<p>(你现在看到的是针对 Rails 4 的版本,所有内容都和 Rails 4 兼容,但这并不是一个新版本,因为 Rails 4 的变化还没大到新出一版。作为一本入门书,本书和之前针对 Rails 3.2 的版本差别很小。小变化虽多(详见<a href="chapter1.html#aside-1-1">旁注 1.1</a>),但主要的变化是一个称为“健壮参数”的新安全技术,会在 <a href="chapter7.html#section-7-3-2">7.3.2 节</a>中介绍。只要 Rails 的变化足够大,我就会新出一版,介绍 Turbolinks 和俄罗斯套娃缓存等技术,还会介绍 RSpec 的新用法,例如“功能测试”。)</p>
<div class="aside box" id="aside-1-1">
<h4><span>旁注 1.1:</span>与第二版的差异</h4>
<p>下面的列表列出了本书和第二版之间几乎所有的差异。(最重要的一个差异是,使用了“健壮参数”,其他都是小变动。)我列出这个列表是为了方便第二版的读者(或者熟悉 Rails 3.2 的读者)快速查看两版的不同之处。如果你没用过 Rails 3.2 请忽略这个列表。</p>
<p>列表的每一项后面都有一个链接,指向变动所在的章节或代码。</p>
<ul>
<li>从 Rails 3.2 升级到 Rails 4.0(<a href="chapter1.html#section-1-2-2">1.2.2 节</a>)</li>
<li>显式引入 Capybara DSL(代码 3.10)</li>
<li>把 RSpec 的 <code>.should</code> 句法换成了 <code>expect().to</code>(<a href="chapter3.html#section-3-2-1">3.2.1 节</a>)</li>
<li>把 <code>have_selector('title', ...)</code> 换成了 <code>have_title(...)</code>(<a href="chapter3.html#section-3-3-1">3.3.1 节</a>)</li>
<li>更新操作所用的 HTTP 请求从 <code>PUT</code> 换成了 <code>PATCH</code>(<a href="chapter3.html#aside-3-3">旁注 3.3</a>)</li>
<li>引入样式表和 JavaScript 脚本时指定了针对 Turbolinks 的参数(代码 3.26)</li>
<li>把 <code>root to: 'path'</code> 换成了 <code>root 'path'</code>(代码 5.24)</li>
<li>把 <code>find_by_thing(...)</code> 换成了 <code>find_by(thing: ...)</code>(<a href="chapter6.html#section-6-1-4">6.1.4 节</a>)</li>
<li>把 <code>rake db:test:prepare</code> 命令换成了 <code>rake test:prepare</code>(<a href="chapter6.html#section-6-2-1">6.2.1 节</a>)</li>
<li>撤掉 <code>attr_accessible</code>,换用“健壮参数”(<a href="chapter7.html#section-7-3-2">7.3.2 节</a>)</li>
<li>换用加密的记忆权标(<a href="chapter8.html#section-8-2-1">8.2.1 节</a>)</li>
<li>把 <code>before_filter</code> 换成了 <code>before_action</code>(代码 9.21)</li>
<li>使用 Capybara 的 <code>match: :first</code> 参数点击第一个匹配的链接(代码 9.42)</li>
<li>把 <code>default_scope</code> 的参数从 Hash 换成了 lambda(代码 10.11)</li>
<li>把 <code>dup</code> 换成了 <code>to_a</code> 方法(代码 10.12)</li>
<li>使用 XPath 测试按钮的状态变化(<a href="chapter11.html#section-11-2-4">11.2.4 节</a>)</li>
</ul>
</div>
<p>注意,本书的目标并不仅仅是教你 Rails,而是教你怎样使用 Rails 进行 Web 开发,教会你为因特网开发软件的技能。除了讲到 Ruby on Rails 之外,涉及到的技术还有 HTML、CSS、数据库、版本控制、测试和部署。为了达成学习目标,本书使用了一个完整的方案:通过实例学习使用 Rails 从零开始创建一个真正的程序。如 <a href="http://sivers.org/">Derek Sivers</a> 在前言中所说的,本书内容采用线性TDD结构,需要从头开始按顺序读到结尾。如果你经常跳着阅读技术类书籍,这种线性的组织方式需要你适应一下。你可以将本书设想为一个电子游戏,学习完每一章就会升一级。(而练习就是每一关的<a href="http://en.wikipedia.org/wiki/Boss_\(video_gaming\)#Miniboss">小怪兽</a>。)</p>
<p>本章首先将介绍如何安装 Ruby on Rails 所需的软件,搭建开发所需的环境(<a href="chapter1.html#section-1-2">1.2 节</a>)。然后创建第一个 Rails 程序 <code>first_app</code>。本书会遵从一些优秀的软件开发习惯,所以在创建第一个程序后我们会立即将它放到版本控制系统 Git 中(<a href="chapter1.html#section-1-3">1.3 节</a>)。最后,我们还将把这个程序放到实际的生产环境中运行(<a href="chapter1.html#section-1-4">1.4 节</a>)。</p>
<p>第 2 章我们会创建第二个程序,演示一些 Rails 程序的基本操作。为了快速创建,我们会使用脚手架功能(<a href="chapter1.html#aside-1-1">旁注 1.1</a>)来创建一个示例程序(名为 <code>demo_app</code>),因为生成的代码还很粗糙也很复杂,第 2 章将集中精力在通过浏览器的 URI (经常称为 URL)<sup class="footnote" id="fnref-1-1"><a href="#fn-1-1" rel="footnote">1</a></sup>来和程序交互这一点上。</p>
<p>本书剩下的章节将介绍从零开始开发一个大型示例程序(名为 <code>sample_app</code>)。在这个程序的开发过程中将使用“测试驱动开发”(Test-driven Development, TDD)理念,从第 3 章开始创建静态页面,然后增加一些动态的内容。第四章则会简要的介绍一下 Rails 背后的 Ruby 程序语言。第五章到第九章将逐步完善这个程序的基础框架:网站的布局,用户数据模型,完整的注册和验证系统。最后在第 10 章和第 11 章将添加微博和社交功能,最终开发出一个可以实际运行的示例网站。</p>
<p>最终的示例程序将在外表上和一个同样采用 Rails 开发的微博网站十分相似<sup class="footnote" id="fnref-1-t1"><a href="#fn-1-t1" rel="footnote">2</a></sup>。虽然我们将主要的精力集中在这个示例程序上了,但是本书的重点却在于提供一些通用的方法,这样你就会具有坚实的基本功,不论开发什么样的 Web 程序都能够派上用场。</p>
<h2 id='section-1-1'><span>1.1</span> 简介</h2>
<p>自 2004 年出现以来,Rails 迅速成为动态 Web 程序开发领域功能最强大、最受欢迎的框架之一。从初创的项目到很多的大公司都在使用 Rails:<a href="http://37signals.com/">37signals</a>,<a href="http://github.com/">Github</a>,<a href="http://shopify.com/">Shopify</a>,<a href="http://scribd.com/">Scribd</a>,<a href="http://twitter.com/">Twitter</a>,<a href="http://disney.com">Disney</a>,<a href="http://hulu.com/">Hulu</a> 和 <a href="http://yellowpages.com/">Yellow Pages</a> 等,<a href="http://rubyonrails.org/applications">这个列表</a>还很长。有很多 Web 开发工作室也在使用 Rails,比如 <a href="http://entp.com/">ENTP</a>,<a href="http://thoughtbot.com/">thoughtbot</a>,<a href="http://pivotallabs.com/">Pivotal Labs</a> 和 <a href="http://hashrocket.com/">Hashrocket</a>,以及无数的独立顾问,培训人员和项目承包商。</p>
<p>是什么使得 Rails 如此成功呢?首先,Ruby on Rails 是完全开源的,基于 <a href="http://www.opensource.org/licenses/mit-license.php">MIT 协议</a>发布,可以免费下载、使用。Rails 的成功有很大一部分是得益于它优雅而紧凑的设计。研习 Ruby 语言的高可扩展性后,Rails 开发了一套用于开发 Web 程序的“<a href="http://en.wikipedia.org/wiki/Domain_Specific_Language">领域专属语言</a>”(Domain-specific Language, DSL)。所以 Web 编程中像生成 HTML、创建数据模型、URL 路由等任务在 Rails 中都很容易实现,最终得到的程序代码很简洁而且可读性较高。</p>
<p>Rails 还会快速跟进 Web 领域最新的技术和框架架构技术。例如,Rails 是最早实现 REST 这个 Web 程序架构体系的框架之一(这一体系将贯穿本书)。当其他的框架开发出成功的新技术后,Rails 的创建者 DHH 及其核心开发团队会毫不犹豫的将其吸纳进来。或许最典型的例子就是 Rails 和 Merb (和 Rails 类似的 Ruby Web 框架)两个项目的合并,这样一来 Rails 就继承了 Merb 的模块化设计、稳定的 API,性能也得到了提升。</p>
<p>最后一点,Rails 有一个活跃而多元化的社区。社区中有数以百计的开源项目<a href="http://contributors.rubyonrails.org/">贡献者</a>,组织了很多<a href="http://railsconf.com/">会议</a>,开发了大量的 <a href="https://rubygems.org/">gem</a>,还有很多内容丰富的博客,一些讨论组和 IRC 频道。有如此多数量的 Rails 程序员也使得处理程序错误变得简单了:“使用 Google 搜索错误信息”的方法几乎总能搜到一篇相关的博客文章或讨论组的话题。</p>
<h3 id='section-1-1-1'><span>1.1.1</span> 给不同读者群的建议</h3>
<p>本书的内容不仅只是讲解 Rails,还会涉及 Ruby 语言、RSpec 测试框架、<a href="http://en.wikipedia.org/wiki/HTML">HTML</a>、<a href="http://en.wikipedia.org/wiki/CSS">CSS</a>、少量的 <a href="http://en.wikipedia.org/wiki/JavaScript">JavaScript</a> 和一些 <a href="http://en.wikipedia.org/wiki/SQL">SQL</a>。所以不管你的 Web 开发技能处在什么层次,读完本书后你就能够继续学习一些较为高级的 Rails 资源了,同时也会对书中提到的其他技术有一个大体的认识。这么说也意味着本书要覆盖很多知识,如果你不是一个有些经验的程序员学起来会觉得有些吃力。下面就根据不同的开发背景给出使用本书的一些建议。</p>
<div class="aside box" id="aside-1-2">
<h4><span>旁注 1.2:</span>脚手架:更快,更简单,更诱人</h4>
<p>Rails 出现伊始就吸引了众多目光,特别是 Rails 创始人 DHH (David Heinemeier Hansson)制作的著名的“<a href="http://www.youtube.com/watch?v=Gzj723LkRJY">15分钟博客程序</a>”视频,该视频以及其衍生版本是窥探 Rails 强大功能一种很好的方式,我推荐你也看一下这些视频。剧透一下:这些视频中的演示能控制在15分钟得益于一个叫做“脚手架(scaffold)”的功能,它通过 Rails 命令 <code>generate</code> 生产大量的代码。</p>
<p>很多人制作 Rails 教程时选择使用脚手架功能,因为它<a href="http://en.wikipedia.org/wiki/Dark_side_(Star_Wars)">更快、更简单、更诱人</a>。不过脚手架会生成大量复杂的代码,会使初学者产生困惑,虽然会用了但却不明白到底发生了什么事。使用脚手架功能可能会把你变成一个脚本生成器的使用者但却不会增进你对 Rails 知识的掌握。</p>
<p>本书将采用一种不同的方式,虽然第二章会用脚手架开发一个小型的示例程序,但本书的核心是从第三章开始开发的较为大型的程序。在开发这个大型程序的每一个阶段我们只会编写少量的代码,易于理解但又具有一定的挑战性。这样的过程最终会让你对 Rails 知识有较为深刻地理解,能灵活运用,创建几乎任何类型的 Web 程序。</p>
</div>
<p><strong>所有读者:</strong>学习 Rails 时一个常见的疑问是,是否要先学习 Ruby。这个问题的答案取决于你个人的学习方式以及你所具有的编程经验。如果你希望较为系统的彻底学习,或者你以前从未编程过,那么先学 Ruby 或许更适合你,我推荐你阅读 Peter Cooper 的《<a href="http://www.amazon.com/gp/product/1430223634">Ruby 入门</a>》一书。很多 Rails 开发初学者很想立马就开始 Web 程序开发,而不是在此之前阅读一本 500 多页纯粹讲解 Ruby 的书。如果你是这类人群,我推荐你在 <a href="http://tryruby.org/">Try Ruby</a> 上学习一些短小的交互式教程,然后还可以看一下 <a href="http://railsforzombies.org/">Rails for Zombies</a> 这个免费的视频教程,看看 Rails 都能做些什么。</p>
<p>另外一个常见的疑问是,是否要在一开始就使用测试。就如前面的介绍所说的,本书会使用“测试驱动开发(也叫“先测试后开发”)”理念,我认为这是使用 Rails 进行 Web 开发最好的方式,但这样也会增加难度和复杂度。如果你觉得做测试有些困难,我建议你在第一遍阅读时直接跳过所有测试,或者(更好的是)只把它们当做验证代码正确性的工具,而不用管测试的机理。如果采用后一种方法,你要创建一些必要的测试文件(叫做 spec),然后将本书中提供的测试代码编写进去,然后运行这些测试用例(<a href="chapter5.html">第五章</a>会介绍)得到失败消息,然后编写代码再运行测试让其通过。</p>
<p><strong>缺乏经验的程序员:</strong>本书的主要读者群不是刚入门的程序员,Web 程序及其相关的任意一个技术都是很复杂的。如果你完全是个 Web 编程菜鸟,发现本书的内容太难了,我建议你先学习基本的 HTML 和 CSS(很可惜这两种技术我没有推荐的书籍,但是《深入浅出 HTML》应该不错,一个读者推荐 David Sawyer McFarland 的《CSS 实战手册》),然后再试着阅读本书。你也可以考虑先阅读 Peter Cooper 的《Ruby 入门》的前几章,这几章中的示例程序都比功能完善的 Web 程序小得多。不过也有一批初学者通过本书学会了 Web 开发,所以你不妨也试一下,而且我强烈推荐<a href="http://railstutorial.org/screencasts">本书配套的教学视频</a>,通过观看别人的操作来学习 Rails 开发。</p>
<p><strong>经验丰富的程序员,但是刚接触 Web 开发:</strong>以前的经验说明你可能已经理解了类、方法、数据结构等概念,这是个好的开始。不过,如果你以前是 C/C++ 或 Java 程序员,你会觉得 Ruby 有点另类,需要花一段时间才能适应;慢慢的适应,你会习惯的。(如果你实在无法放弃使用行尾的分号,Ruby 允许你这么做)本书会为你介绍所有 Web 相关的概念,所以如果你现在并不知道 <code>POST</code> 和 <code>PATCH</code> 的区别也不要紧。</p>
<p><strong>经验丰富的 Web 开发者,但是刚接触 Rails:</strong>你有很好的基础了,如果你曾经使用过 PHP 或 Python(更好)这些动态语言就更好了。我们要讲的基础都是一致的,但是你可能对 TDD 还有 Rails 采用的 REST 架构感到陌生。而且 Ruby 语言有自己的风格,这一点对你来说也是陌生的。</p>
<p><strong>经验丰富的 Ruby 程序员:</strong>如今 Ruby 程序员不懂 Rails 的很少,如果你是这种情况,可以快速的过一遍本书,然后自己动手开发一个应用程序。</p>
<p><strong>缺乏经验的 Rails 程序员:</strong>你或许阅读过其他的 Rails 教程,也开发过小型的 Rails 程序。根据一些读者的反馈,本书还是会给你带来帮助,别的不说,单就时效性而言,本书会比你当初学习 Rails 使用的教程要更新一些。</p>
<p><strong>经验丰富的 Rails 程序员:</strong>你不需要阅读本书了,但是很多经验丰富的 Rails 开发者还是说他们从本书中学到了很多,或许通过本书你会换个角度来看 Rails。</p>
<p>读完本书后,我建议经验丰富的程序员继续阅读 David A. Black 的《<a href="http://www.amazon.com/gp/product/1933988657">The Well-Grounded Rubyist</a>》,Russ Olsen 的《<a href="http://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional-Series/dp/0321584104/?version=4.0#">Eloquent Ruby</a>》,或者 Hal Fulton 的《<a href="http://www.amazon.com/gp/product/0672328844">Ruby 之道</a>》,这本也是进阶书籍,不过更为专注某些特定的话题。</p>
<p>不管你是从哪里开始的,学完本书你还应该继续学习一些中高级 Rails 资源。以下是我推荐的学习资源<sup class="footnote" id="fnref-1-t2"><a href="#fn-1-t2" rel="footnote">3</a></sup>:</p>
<ul>
<li><a href="http://railscasts.com/">RailsCasts</a>,Ryan Bates:优秀的免费(大多数)视频教程</li>
<li><a href="http://peepcode.com">PeepCode</a>:优秀的收费视频教程</li>
<li><a href="http://www.codeschool.com/">Code School</a>:交互式的编程课程</li>
<li><a href="http://guides.rubyonrails.org/">Rails 官方指南</a>:按话题编写经常更新的 Rails 参考</li>
<li><a href="http://railscasts.com/">Ryan Bates 的 RailsCasts</a>:我是不是已经说过 RailsCasts了?真的,强烈推荐 RailsCasts。</li>
</ul>
<h3 id='section-1-1-2'><span>1.1.2</span> Rails 的性能</h3>
<p>在继续介绍之前,我想花点时间说明一下 Rails 框架发布初期一个备受指责的问题:Rails 的性能很不好,例如不能处理较大的访问量。这个问题之所以存在是因为有些人没搞清状况,性能是要在你的网站中优化,而不是在框架中,强大的 Rails 只是一个框架而已。所以上面的问题应该换个角度来看:使用 Rails 开发的网站可以做性能优化吗?这样的问题已经得到了肯定的回答,因为很多世界上访问量最大的网站就是用 Rails 开发的。实际上性能优化涉及到的不仅仅是 Rails,如果你的程序需要处理类似 Hulu 或 Yellow Pages 这种数量级的访问量,Rails 并不会拖你的后腿。</p>
<h3 id='section-1-1-3'><span>1.1.3</span> 本书排版约定</h3>
<p>本书中使用的排版约定很多都是不言自明的,在本节我要说一下那些意义不是很清晰的部分。</p>
<p>本书的 HTML 版和 PDF 版都包含了大量的链接,有内部各章节之间的链接(例如 <a href="chapter1.html#section-1-2">1.2</a>节),也有链接到其他网站的链接(例如<a href="http://rubyonrails.org/download">Ruby on Rails 下载</a>页面)。<sup class="footnote" id="fnref-1-2"><a href="#fn-1-2" rel="footnote">4</a></sup></p>
<p>本书中很多例子都用到了命令行命令,为了行文方便,所有的命令行示例都使用了 Unix 风格的命令行提示符(美元符号),例如:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span><span class="nb">echo</span> <span class="s2">"hello, world"</span>
hello, world
</pre></div>
</div>
<p>Windows 用户要知道在 Windows 中命令行的提示符是 <code>></code>:</p>
<div class="codeblock"><div class="highlight type-plaintext"><pre>C:\Sites> echo "hello, world"
hello, world
</pre></div>
</div>
<p>在 Unix 系统中,一些命令要使用 <code>sudo</code>(超级用户的工作,“substitute user do”)执行。<sup class="footnote" id="fnref-1-14"><a href="#fn-1-14" rel="footnote">5</a></sup>默认情况下,使用 <code>sudo</code> 执行的命令是以管理员的身份执行的,这样就能访问普通用户无法访问的文件和文件夹了。例如 <a href="chapter1.html#section-1-2-2">1.2.2 节</a>中的一个例子:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>sudo ruby setup.rb
</pre></div>
</div>
<p>在多数的 Unix/Linux/OS X 系统中默认需要使用 <code>sudo</code>,但是如果使用下面介绍的 Ruby 版本管理工具就没必要使用了,直接使用以下命令即可:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>ruby setup.rb
</pre></div>
</div>
<p>Rails 附带了很多可以在命令行中运行的命令。例如,在 <a href="chapter1.html#section-1-2-5">1.2.5 节</a>中将使用下面的命令在本地运行一个开发服务器:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rails server
</pre></div>
</div>
<p>和命令提示符一样,本书也使用了 Unix 风格文件夹分隔符(例如,一个斜线 /)。例如,我的示例程序存放在:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>/Users/mhartl/rails_projects/sample_app
</pre></div>
</div>
<p>在 Windows 中等价的文件夹可能是:</p>
<div class="codeblock"><div class="highlight type-plaintext"><pre>C:\Sites\sample_app
</pre></div>
</div>
<p>一个程序的根目录称为“Rails 根目录”,但是这个称呼很容易让一些人产生困惑,他们以为“Rails 根目录”是指 Rails 框架的根目录。为了避免歧义,本书将使用“程序根目录”替代“Rails 根目录”的称呼,程序中所有文件夹都是相对该目录的。例如,示例程序的 <code>config</code> 目录是:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>/Users/mhartl/rails_projects/sample_app/config
</pre></div>
</div>
<p>这个程序的根目录就是 <code>config</code> 之前的部分:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>/Users/mhartl/rails_projects/sample_app
</pre></div>
</div>
<p>为了方便,如果需要指向下面这个文件</p>
<div class="codeblock"><div class="highlight type-shell"><pre>/Users/mhartl/rails_projects/sample_app/config/routes.rb
</pre></div>
</div>
<p>我会省略前面的程序根目录,直接写成 <code>config/routes.rb</code>。</p>
<p>本书经常需要显示一些来自其他程序(命令行,版本控制系统,Ruby 程序等)的输出,因为系统之间存在差异,你所得到的输出结果可能和本书中的不同,但是无需担心。</p>
<p>你在使用某些命令时可能会导致一些错误的发生,我不会一一列举各个错误的解决方法,你可以自行通过 Google 搜索解决。如果你在学习本书的过程中遇到了问题,我建议你看一下<a href="http://railstutorial.org/help">本书帮助页面</a>中列出的资源。</p>
<h2 id='section-1-2'><span>1.2</span> 搭建环境</h2>
<blockquote>
<p>我认为第一章就像法学院的“淘汰阶段”一样,如果你能成功的搭建开发环境,后面就会很顺利。</p>
<p>– 本书读者 Bob Cavezza</p>
</blockquote>
<p>现在可以开始搭建 Ruby on Rails 开发环境并创建第一个程序了。本节的知识量比较大,特别是对于没有很多编程经验的人来说,所以如果在某个地方卡住了也不要灰心,不只你一个人如此,每个开发者都是从这一步走过来的,慢慢来,功夫不负有心人。</p>
<h3 id='section-1-2-1'><span>1.2.1</span> 开发环境</h3>
<p>不同的人有不同的喜好,每个 Rails 程序员都有一套自己的开发环境,但基本上分为两类:文本编辑器+命令行的环境和“集成开发环境”(IDE=Integrated Development Environment)。先来说说后一种。</p>
<h4 id='section-1-2-1-1'><span></span>IDE</h4>
<p>使用最多的 Rails IDE 是 <a href="http://www.aptana.com/rails/">RadRails</a> 和 <a href="http://www.jetbrains.com/ruby/index.html">RubyMine</a>。我听说 RubyMine 不错,一个读者(David Loeffler)还总结了一篇文章讲解<a href="https://github.com/perfectionist/sample_project/wiki">如何结合本书使用 RubyMine</a>。如果你习惯使用 IDE,我建议你把上面提到的几个全都试一下,找到最符合自己要求的一款。</p>
<div class="figure" id="figure-1-1">
<img src="figures/editor_shell.png" alt="editor shell" />
<p class="caption"><span>图 1.1:</span>文本编辑器和命令行的开发环境</p>
</div>
<h4 id='section-1-2-1-2'><span></span>文本编辑器和命令行</h4>
<p>较之 IDE,我更喜欢使用文本编辑器编辑文本,使用命令行执行命令(如图 1.1)。如何组合取决于你的喜好和所用的平台。</p>
<ul>
<li><strong>文本编辑器:</strong>我推荐使用 <a href="http://www.sublimetext.com/2">Sublime Text 2</a>,这是一个跨平台支持的文本编辑器,简单易学且功能强大。<sup class="footnote" id="fnref-1-15"><a href="#fn-1-15" rel="footnote">6</a></sup>Sublime Text 深受 <a href="http://macromates.com/">Textmate</a> 的影响,它能兼容大多数 Textmate 的定制功能,例如代码片段和配色方案。(Textmate 只可在 OS X 中使用,如果你使用 Mac 的话,它仍然是一个很好的选择。)另外一个很好的选择是 <a href="http://www.vim.org/">Vim</a> <sup class="footnote" id="fnref-1-3"><a href="#fn-1-3" rel="footnote">7</a></sup>,它有针对各种主要平台的版本。Sublime Text 需要付费,而 Vim 则是免费的。二者都是界内人士普遍使用的编辑器,但就我的经验而言,Sublime Text 对初学者更友好。</li>
<li><strong>终端(命令行):</strong>OS X 系统中我推荐使用 <a href="http://iterm.sourceforge.net/">iTerm</a> 或是内置的终端程序。Linux 系统默认的终端就很好。在 Windows 中,很多用户选择在虚拟机中运行 Linux 来开发 Rails 程序,那么终端就使用默认的好了。如果你是在纯 Windows 系统中开发,我推荐使用 <a href="http://railsinstaller.org/">Rails Installer</a> 中附带的终端。</li>
</ul>
<p>如果你决定使用 Sublime Text,可以参照<a href="https://github.com/mhartl/rails_tutorial_sublime_text">针对本书的安装说明</a>来安装。(这些设置可能有些繁琐,且易于出错,所以我只推荐给高级用户使用。即便不做这些设置,Sublime Text 也是编写 Rails 应用程序的绝佳工具。)</p>
<h4 id='section-1-2-1-3'><span></span>浏览器</h4>
<p>虽然浏览器有很多选择,但是大多数的 Rails 开发者使用 Firefox、Safari 或 Chrome 进行开发。这三个浏览器都内建了“查看元素功能”,在页面中右键点击(或加 Control 键)可以调出。</p>
<h4 id='section-1-2-1-4'><span></span>关于工具的一点说明</h4>
<p>在搭建开发环境的过程中,你会发现花费了很多时间来熟悉各种工具。特别是学习编辑器和 IDE,需要花费特别长的时间。单单用在 Sublime Text 和 Vim 教程上的时间就可能是几个星期。如果你刚刚接触这一领域,我要告诉你,学习工具要花费时间是正常的。每个人都是这样过来的。有时你会抓狂,当你在脑中有了很好的程序构思时,你只想学习 Rails,但却要浪费一个星期去学习老旧的 Unix 编辑器,这时很容易失去耐心。但请记住,工欲善其事必先利其器。</p>
<h3 id='section-1-2-2'><span>1.2.2</span> 安装 Ruby,RubyGems,Rails 和 Git</h3>
<blockquote>
<p>世界上几乎所有的软件不是无法使用就是很难使用。所以用户惧怕软件。用户们已经得到经验了,不论是安装软件还是填写一个在线表格,都不会成功。我也害怕安装东西,可笑的是我还是个计算机科学博士。</p>
<p>– Paul Graham,《创业者》,Jessica Livingston 著</p>
</blockquote>
<p>现在可以安装 Ruby on Rails 了。我会尽量讲得浅一点,但是系统之间存在差异,很多地方都可能出现问题,如果你遇到问题的话请通过 Google 搜索,或访问<a href="http://railstutorial.org/help">本书的帮助页面</a>。</p>
<p>除非有特殊说明,你应该使用和本书中所有软件的相同的版本,包括 Rails,这样才能得到相同的结果。有时候不同的补丁版本会产生相同的结果,但不完全相同,特别是针对 Rails 的版本。不过 Ruby 是个例外,1.9.2、1.9.3 和 2.0.0 都可以用于本教程,所以三者随意选择。</p>
<h4 id='section-1-2-2-1'><span></span>Rails Installer(Windows)</h4>
<p>以前在 Windows 中安装 Rails 是件很痛苦的事,但多亏了 <a href="http://engineyard.com/">Engine Yard</a> 公司的大牛们,特别是 Nic Williams 博士和 Wayne E. Seguin,现在在 Windows 中安装 Rails 及相关的软件简单多了。如果你使用 Windows 的话,可以到 <a href="http://railsinstaller.org/">Rails Installer 的网站</a>下载 Rails Installer 安装程序,顺便可以看一下安装视频。双击安装文件按照说明安装 Git、Ruby、RubyGems 和 Rails。安装完成后你就可以直接跳到 <a href="chapter1.html#section-1-2-3">1.2.3 节</a>去创建第一个应用程序了。</p>
<p>有一点需要说明,使用 Rails Installer 安装的 Rails 版本可能和下面介绍的方法得到的版本不一致,这可能会导致不兼容的问题。为了解决这个问题,我现在正在与 Nic 和 Wayne 一起工作,按照 Rails 版本号的顺序列出一个 Rails Installer 列表。</p>
<h4 id='section-1-2-2-2'><span></span>安装 Git</h4>
<p>Rails 社区中的人多少都会使用一个叫 Git(<a href="chapter1.html#section-1-3">1.3 节</a>中会详细介绍)的版本控制系统,因为大家都这么做,所以你在一开始就要开始用 Git。如何在你使用的平台中安装 Git 可以参考<a href="http://git-scm.com/book/zh/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git">《Pro Git》书中的“安装 Git”一节</a>。</p>
<h4 id='section-1-2-2-3'><span></span>安装 Ruby</h4>
<p>接下来要安装 Ruby 了。(安装的过程可能很痛苦也容易出错,其实我也很害怕安装 Ruby 新版本,不过这是学习的必经之路。)</p>
<p>很有可能你使用的系统已经自带了 Ruby,你可以执行下面的命令来看一下:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>ruby -v
</pre></div>
</div>
<p>这个命令会显示 Ruby 的版本。Rails 4 需要使用 Ruby 1.9 或以上的版本,但最好是 Ruby 2.0。(基本上无法使用 Ruby 1.8.7。)本教程假设多数的读者使用的是 Ruby 1.9.3 或 2.0.0,不过 Ruby 1.9.2 应该也可以用。</p>
<p>如果你使用的是 OS X 或者 Linux,在安装 Ruby 时我强烈建议使用 Ruby 版本管理工具 <a href="http://rvm.io/">RVM</a>,它允许你在同一台电脑上安装并管理多个 Ruby 版本。(在 Windows 中可以使用 <a href="http://github.com/vertiginous/pik">Pik</a>)如果你希望在同一台电脑中运行不同版本的 Ruby 或 Rails 就需要它了。如果你在使用 RVM 时遇到什么问题的话,可以在 RVM 的 IRC 频道(<a href="http://webchat.freenode.net/?channels=rvm">freenode.net 上的 #rvm</a>)中询问它的开发者 Wayne E. Seguin。<sup class="footnote" id="fnref-1-4"><a href="#fn-1-4" rel="footnote">8</a></sup>如果你使用的是 Linux,我推荐你阅读 Sudobits 博客中的《<a href="http://blog.sudobits.com/2012/05/02/how-to-install-ruby-on-rails-in-ubuntu-12-04-lts/">如何在 Ubuntu 中安装 Ruby on Rails</a>》一文。</p>
<p>在此之前,OS X 用户可能要先安装 Xcode 开发者工具。相对于安装整个工具包我更推荐你安装较小的 <a href="https://developer.apple.com/downloads/">Xcode 命令行工具包</a>。</p>
<p>在安装 Ruby 之前,先要<a href="http://rvm.io/rvm/install/">安装 RVM</a>:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>curl -sSL https://get.rvm.io | bash -s
</pre></div>
</div>
<p>(如果你已经安装了 RVM,应该运行下面的命令</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rvm get stable
</pre></div>
</div>
<p>确保安装的是最新版本。)</p>
<p>然后运行下面的命令检查安装 Ruby 的需求条件:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rvm requirements
</pre></div>
</div>
<p>如果提示“command not found”,可以运行下面的命令:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span><span class="nb">source</span> ~/.rvm/scripts/rvm
</pre></div>
</div>
<p>在我的系统中,要安装以下所示的库(使用 <a href="http://mxcl.github.com/homebrew/">Homebrew</a>,OS X 中的包管理系统):</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>brew install libtool libxslt libksba openssl
</pre></div>
</div>
<p>在 Linux 中,可以使用 <code>apt-get</code> 或 <code>yum</code>。</p>
<p>我还得安装 <a href="https://en.wikipedia.org/wiki/YAML">YAML</a> 库:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="c"># For Mac with Homebrew</span>
<span class="gp">$ </span>brew install libyaml
<span class="c"># For Debian-based Linux systems</span>
<span class="gp">$ </span>apt-get install libyaml-dev
<span class="c"># For Fedora/CentOS/RHEL Linux systems</span>
<span class="gp">$ </span>yum install libyaml-devel
</pre></div>
</div>
<p>最后,我要告知 RVM,OpenSSL 的安装位置,才能安装 Ruby 2.0.0:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rvm install 2.0.0 --with-openssl-dir<span class="o">=</span><span class="nv">$HOME</span>/.rvm/usr
<<span class="nb">wait </span>a <span class="k">while</span>>
</pre></div>
</div>
<p>这样,至少在我的系统中,Ruby 2.0.0 已经成功安装了。</p>
<p>不过,安装的过程很容易出错。我尽力说明了常用的方法,更通用的方式是依靠搜索,然后自己解决。</p>
<p>安装 Ruby 之后,要配置一下你的系统,这样其他程序才能运行 Rails。这个过程会涉及到 gem 的安装,gem 是 Ruby 代码的打包系统。因为不同版本的 gem 会有差异,我们经常要创建一个额外的 gem 集(gemset),包含一系列的 gem。针对本教程,我推荐你创建一个名为 <code>railstutorial_rails_4_0</code> 的 gemset:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rvm use 2.0.0@railstutorial_rails_4_0 --create --default
Using /Users/mhartl/.rvm/gems/ruby-2.0.0-p0 with gemset railstutorial_rails_4_0
</pre></div>
</div>
<p>上面的命令会使用 Ruby 2.0.0 创建(<code>--create</code>)一个名为 <code>railstutorial_rails_4_0</code> 的 gemset,然后立马就开始使用(<code>use</code>) 这个 gemset,并将其设为默认的(<code>--default</code>) gemset,这样每次打开新的终端就会自动使用 <code>2.0.0@railstutorial_rails_4_0</code> 这个 Ruby 和 gemset 的组合。RVM 提供了大量的命令用来处理 gemset,更多内容可以查看其文档(<a href="http://rvm.io/gemsets/">http://rvm.io/gemsets/</a>)。如果你在使用 RVM 时遇到了问题,可以运行以下的命令显示帮助信息:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rvm <span class="nb">help</span>
<span class="gp">$ </span>rvm gemset <span class="nb">help</span>
</pre></div>
</div>
<h4 id='section-1-2-2-4'><span></span>安装 RubyGems</h4>
<p>RubyGems 是 Ruby 项目的包管理程序,有很多有用的代码库(包括 Rails)都可以通过包(或叫做 gem)的形式获取。安装 Ruby 后再安装 RubyGems 就很简单了。如果你安装了 RVM 就已经安装 RubyGems 了,因为 RVM 已经自动将其安装了:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>which gem
/Users/mhartl/.rvm/rubies/ruby-2.0.0-p0/bin/gem
</pre></div>
</div>
<p>如果你还没有安装 RubyGems,可以<a href="http://rubyforge.org/frs/?group_id=126">下载 RubyGems</a>,解压文件,然后进入 <code>rubygems</code> 目录运行安装程序:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>ruby setup.rb
</pre></div>
</div>
<p>(如果你遇到了权限错误的提示,参照 <a href="chapter1.html#section-1-1-3">1.1.3</a> 节所说的,要使用 <code>sudo</code>。)</p>
<p>安装 RubyGems 之后,要确保你使用的版本和本书一致:</p>
<div class="codeblock"><div class="highlight type-shell"><pre>gem update --system 2.1.9
</pre></div>
</div>
<p>将你的系统定格在这个版本可以避免以后因为 RubyGems 升级而产生的差异。</p>
<p>安装 gem 时,默认情况下 RubyGems 会生成两种不同的文档(ri 和 rdoc),但是很多 Ruby 和 Rails 开发者认为花时间生成这些文档没什么必要。(很多程序员更依靠在线文档,而不是内置的 ri 和 rdoc 文档。)为了禁止自动生成文档,我建议你执行代码 1.1 中的命令,在家目录(home directory)中创建一个名为 <code>.gemrc</code> 的 gem 配置文件,文件的内容参见代码 1.2。(波浪号“~”代表“家目录”,<code>.gemrc</code> 中的点号代表这是个隐藏文件,配置文件一般都是隐藏的。)</p>
<div class="codeblock has-caption" id="codeblock-1-1"><p class="caption"><span>代码 1.1:</span>创建 gem 配置文件</p><div class="highlight type-shell"><pre><span class="gp">$ </span>subl ~/.gemrc
</pre></div>
</div>
<p>这里的 <code>subl</code> 是 OS X 中启动 Sublime Text 的命令,你可以参照 Sublime Text 2 文档中的 “<a href="http://www.sublimetext.com/docs/2/osx_command_line.html">OS X 命令</a>”一文进行设置。如果你使用的是其他系统,或者你使用的是其他的编辑器,只需换用其他相应的命令(例如,你可以直接双击来启动程序,或者使用其他的命令,如 <code>mate</code>、<code>vim</code>、<code>gvim</code> 或 <code>mvim</code>)。为了行文简洁,在本书后续的内容中当我说使用 <code>subl</code> 时,我的意思是“使用你喜好的文本编辑器打开”。</p>
<div class="codeblock has-caption" id="codeblock-1-2"><p class="caption"><span>代码 1.2:</span>在 <code>.gemrc</code> 中配置不生成 ri 和 rdoc 文档</p><div class="highlight type-plaintext"><pre>install: --no-rdoc --no-ri
update: --no-rdoc --no-ri
</pre></div>
</div>
<h4 id='section-1-2-2-5'><span></span>安装 Rails</h4>
<p>安装完 RubyGems 后安装 Rails 也就简单了。本教程使用 Rails 4.0,通过以下命令安装<sup class="footnote" id="fnref-1-t3"><a href="#fn-1-t3" rel="footnote">9</a></sup>:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>gem install rails --version 4.0.4 --no-ri --no-rdoc
</pre></div>
</div>
<p>(如果你按照上一节所述,设置了 <code>.gemrc</code>,就不必加上最后两个选项了。但是当前的 Rails 4 候选版本<strong>必须</strong>要加上,所以我才写上的。)检查 Rails 是否安装成功,执行以下命令显示 Rails 的版本号:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rails -v
Rails 4.0.4
</pre></div>
</div>
<p>注意:如果你是通过前面介绍的 Rails Installer 安装的 Rails,所得到的版本号可能会有些不同。在写这本书的时候,版本的不同还不会带来大的问题,但是如果 Rails 升级到了更高的版本,问题可能就很严重了。我目前正在和 Engine Yard 一起工作来创建一个 Rails Installer 版本列表。</p>
<p>如果你使用的是 Linux,现在或许还需要安装一些其他的代码包:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>sudo apt-get install libxslt-dev libxml2-dev libsqlite3-dev <span class="c"># 只针对 Linux</span>
</pre></div>
</div>
<p>或者使用 yum:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>sudo yum install libxslt-devel libxml2-devel libsqlite3-devel
</pre></div>
</div>
<h3 id='section-1-2-3'><span>1.2.3</span> 第一个程序</h3>
<p>Rails 程序一般都是从 <code>rails new</code> 命令开始的,这个命令会在你指定的文件夹中创建一个 Rails 程序模板。首先为你的 Rails 程序新建一个文件夹,然后执行 <code>rails new</code> 命令创建第一个程序(参见代码 1.3):</p>
<div class="codeblock has-caption" id="codeblock-1-3"><p class="caption"><span>代码 1.3:</span>运行 <code>rails new</code> 生成一个新程序</p><div class="highlight type-shell"><pre><span class="gp">$ </span>mkdir rails_projects
<span class="gp">$ </span><span class="nb">cd </span>rails_projects
<span class="gp">$ </span>rails new first_app
create
create README.rdoc
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/javascripts/application.js
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
.
.
.
run bundle install
.
.
.
Your bundle is <span class="nb">complete</span>! Use <span class="sb">`</span>bundle show <span class="o">[</span>gemname]<span class="sb">`</span> to see where a bundled
gem is installed.
</pre></div>
</div>
<p>如代码 1.3 所示,运行 <code>rails new</code> 命令会在文件创建完之后自动执行 <code>bundle install</code>。如果这一步没有正确执行,先不要担心,按照 <a href="chapter1.html#section-1-2-4">1.2.4 节</a>中的步骤来做应该就可以了。</p>
<div class="table has-caption" id="table-1-1"><p class="caption"><span>表格 1.1:</span>简单介绍 Rails 默认文件结构</p><table>
<thead>
<tr>
<th>文件/文件夹</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>app/</code></td>
<td>程序的核心文件,包含模型、视图、控制器和帮助方法</td>
</tr>
<tr>
<td><code>app/assets</code></td>
<td>程序的资源文件,如 CSS、JavaScript 和图片</td>
</tr>
<tr>
<td><code>bin/</code></td>
<td>可执行文件</td>
</tr>
<tr>
<td><code>config/</code></td>
<td>程序的设置</td>
</tr>
<tr>
<td><code>db/</code></td>
<td>数据库文件</td>
</tr>
<tr>
<td><code>doc/</code></td>
<td>程序的文档</td>
</tr>
<tr>
<td><code>lib/</code></td>
<td>代码库文件</td>
</tr>
<tr>
<td><code>lib/assets</code></td>
<td>代码库包含的资源文件,如 CSS、JavaScript 和 图片</td>
</tr>
<tr>
<td><code>log/</code></td>
<td>程序的日志文件</td>
</tr>
<tr>
<td><code>public/</code></td>
<td>公共(例如浏览器)可访问的数据,如出错页面</td>
</tr>
<tr>
<td><code>script/rails</code></td>
<td>生成代码、打开终端会话或开启本地服务器的脚本</td>
</tr>
<tr>
<td><code>test/</code></td>
<td>程序的测试文件(在 <a href="chapter3.html#section-3-2-1">3.1.2 节</a> 中换用 <code>spec/</code>)</td>
</tr>
<tr>
<td><code>tmp/</code></td>
<td>临时文件</td>
</tr>
<tr>
<td><code>vendor/</code></td>
<td>第三方代码,如插件和 gem</td>
</tr>
<tr>
<td><code>vendor/assets</code></td>
<td>第三方代码包含的资源文件,如 CSS、JavaScript 和图片</td>
</tr>
<tr>
<td><code>README.rdoc</code></td>
<td>程序简介</td>
</tr>
<tr>
<td><code>Rakefile</code></td>
<td><code>rake</code> 命令包含的任务</td>
</tr>
<tr>
<td><code>Gemfile</code></td>
<td>该程序所需的 gem</td>
</tr>
<tr>
<td><code>Gemfile.lock</code></td>
<td>一个 gem 的列表,确保本程序的复制版使用相同版本的 gem</td>
</tr>
<tr>
<td><code>config.ru</code></td>
<td><a href="http://rack.rubyforge.org/doc/">Rack 中间件</a>的配置文件</td>
</tr>
<tr>
<td><code>.gitignore</code></td>
<td>git 忽略的文件类型</td>
</tr>
</tbody>
</table>
</div>
<p>留意一下 <code>rails</code> 命令创建的文件和文件夹。这些标准的文件夹和文件结构(如图 1.2)是 Rails 的很多优势之一,能让你从零开始快速的创建一个可运行的简单的程序。而且因为这样的结构对 Rails 程序都是一致的,阅读其他人的代码时就显得很亲切。表格 1.1 是这些文件的简介,在本书的后续内容中将介绍其中的大多数。从 <a href="chapter5.html#section-5-2-1">5.2.1 节</a> 开始,首先将介绍 <code>app/assets</code> 文件夹,它是 asset pipeline(Rails 3.1 新增)的一部分,这个功能让组织和部署 CSS 和 JavaScript 等资源文件变得异常简单。</p>
<h3 id='section-1-2-4'><span>1.2.4</span> Bundler</h3>
<p>创建完一个新的 Rails 程序后,你可以使用 Bundler 来安装和包含该程序所需的 gem。在 <a href="chapter1.html#section-1-2-3">1.2.3 节</a> 中提到过,<code>rails</code> 命令会自动执行 Bundler(通过 <code>bundle install</code>),不过本节将对程序默认包含的 gem 做些修改,然后再运行 Bundler。首先在你喜好的文本编辑器中打开 <code>Gemfile</code> 文件:</p>
<div class="figure" id="figure-1-2">
<img src="figures/directory_structure_rails_4_0.png" alt="directory structure rails40" />
<p class="caption"><span>图 1.2:</span>新创建的 Rails 程序的文件结构</p>
</div>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span><span class="nb">cd </span>first_app/
<span class="gp">$ </span>subl Gemfile
</pre></div>
</div>
<p>该文件内容如代码 1.4。这些代码就是常规的 Ruby 代码,现在无需关注句法,第四章将会详细的介绍 Ruby。</p>
<div class="codeblock has-caption" id="codeblock-1-4"><p class="caption"><span>代码 1.4:</span><code>first_app</code> 默认的 <code>Gemfile</code> 文件</p><div class="highlight type-ruby"><pre><span class="n">source</span> <span class="s1">'https://rubygems.org'</span>
<span class="c1"># Use sqlite3 as the database for Active Record</span>
<span class="n">gem</span> <span class="s1">'sqlite3'</span>
<span class="c1"># Use SCSS for stylesheets</span>
<span class="n">gem</span> <span class="s1">'sass-rails'</span><span class="p">,</span> <span class="s1">'~> 4.0.1'</span>
<span class="c1"># Use Uglifier as compressor for JavaScript assets</span>
<span class="n">gem</span> <span class="s1">'uglifier'</span><span class="p">,</span> <span class="s1">'>= 1.3.0'</span>
<span class="c1"># Use CoffeeScript for .js.coffee assets and views</span>
<span class="n">gem</span> <span class="s1">'coffee-rails'</span><span class="p">,</span> <span class="s1">'~> 4.0.0'</span>
<span class="c1"># See https://github.com/sstephenson/execjs#readme for more supported runtimes</span>
<span class="c1"># gem 'therubyracer', platforms: :ruby</span>
<span class="c1"># Use jquery as the JavaScript library</span>
<span class="n">gem</span> <span class="s1">'jquery-rails'</span>
<span class="c1"># Turbolinks makes following links in your web application faster.</span>
<span class="c1"># Read more: https://github.com/rails/turbolinks</span>
<span class="n">gem</span> <span class="s1">'turbolinks'</span>
<span class="c1"># Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder</span>
<span class="n">gem</span> <span class="s1">'jbuilder'</span><span class="p">,</span> <span class="s1">'~> 1.0.1'</span>
<span class="n">group</span> <span class="p">:</span><span class="n">doc</span> <span class="k">do</span>
<span class="c1"># bundle exec rake doc:rails generates the API under doc/api.</span>
<span class="n">gem</span> <span class="s1">'sdoc'</span><span class="p">,</span> <span class="ss">require: </span><span class="kp">false</span>
<span class="k">end</span>
<span class="c1"># Use ActiveModel has_secure_password</span>
<span class="c1"># gem 'bcrypt-ruby', '~> 3.0.0'</span>
<span class="c1"># Use unicorn as the app server</span>
<span class="c1"># gem 'unicorn'</span>
<span class="c1"># Use Capistrano for deployment</span>
<span class="c1"># gem 'capistrano', group: :development</span>
<span class="c1"># Use debugger</span>
<span class="c1"># gem 'debugger', group: [:development, :test]</span>
</pre></div>
</div>
<p>其中很多行代码都用 <code>#</code> 注释掉了,这些代码放在这是告诉你一些常用的 gem,也展示了 Bundler 的句法。现在,除了默认的 gem 我们还不需要其他的 gem。</p>
<p>如果不为 <code>gem</code> 命令指定一个版本号,Bundler 会自动安装 gem 的最新版本。有些 gem 的更新会带来细微但有时会破坏代码的差异,所以在本教程中我们特意加入了可以正常运行的 gem 版本号,如代码 1.5 所示(同时我们也将注释掉的代码去掉了)。</p>
<div class="codeblock has-caption" id="codeblock-1-5"><p class="caption"><span>代码 1.5:</span>指定了 gem 版本号的 <code>Gemfile</code> 文件</p><div class="highlight type-ruby"><pre><span class="n">source</span> <span class="s1">'https://rubygems.org'</span>
<span class="n">ruby</span> <span class="s1">'2.0.0'</span>
<span class="n">gem</span> <span class="s1">'rails'</span><span class="p">,</span> <span class="s1">'4.0.4'</span>
<span class="n">group</span> <span class="p">:</span><span class="n">development</span> <span class="k">do</span>
<span class="n">gem</span> <span class="s1">'sqlite3'</span><span class="p">,</span> <span class="s1">'1.3.8'</span>
<span class="k">end</span>
<span class="n">gem</span> <span class="s1">'sass-rails'</span><span class="p">,</span> <span class="s1">'4.0.1'</span>
<span class="n">gem</span> <span class="s1">'uglifier'</span><span class="p">,</span> <span class="s1">'2.1.1'</span>
<span class="n">gem</span> <span class="s1">'coffee-rails'</span><span class="p">,</span> <span class="s1">'4.0.1'</span>
<span class="n">gem</span> <span class="s1">'jquery-rails'</span><span class="p">,</span> <span class="s1">'2.2.1'</span>
<span class="n">gem</span> <span class="s1">'turbolinks'</span><span class="p">,</span> <span class="s1">'1.1.1'</span>
<span class="n">gem</span> <span class="s1">'jbuilder'</span><span class="p">,</span> <span class="s1">'1.0.2'</span>
<span class="n">group</span> <span class="p">:</span><span class="n">doc</span> <span class="k">do</span>
<span class="n">gem</span> <span class="s1">'sdoc'</span><span class="p">,</span> <span class="s1">'0.3.20'</span><span class="p">,</span> <span class="ss">require: </span><span class="kp">false</span>
<span class="k">end</span>
</pre></div>
</div>
<p>代码 1.5 加入了下面这行</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">ruby</span> <span class="s1">'2.0.0'</span>
</pre></div>
</div>
<p>说明应用程序期望使用的 Ruby 版本,在部署时特别有用(参见 <a href="chapter1.html#section-1-4">1.4 节</a>)。(如果你使用的不是 Ruby 2.0.0,需要修改到实际的版本号。)</p>
<p>更新后的 <code>Gemfile</code> 还把 Rails 默认使用的 JavaScript 库 jQuery 的 gem 从</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">gem</span> <span class="s1">'jquery-rails'</span>
</pre></div>
</div>
<p>改为</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">gem</span> <span class="s1">'jquery-rails'</span><span class="p">,</span> <span class="s1">'2.2.1'</span>
</pre></div>
</div>
<p>同时也将</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">gem</span> <span class="s1">'sqlite3'</span>
</pre></div>
</div>
<p>修改成</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">group</span> <span class="p">:</span><span class="n">development</span> <span class="k">do</span>
<span class="n">gem</span> <span class="s1">'sqlite3'</span><span class="p">,</span> <span class="s1">'1.3.8'</span>
<span class="k">end</span>
</pre></div>
</div>
<p>强制 Bundler 安装 <code>sqlite3</code> gem 的 <code>1.3.8</code> 版。注意,我们仅把 SQLite 放到了开发环境中(<a href="chapter7.html#section-7-1-1">7.1.1 节</a>),这样可以避免和 Heroku(<a href="chapter1.html#section-1-4">1.4 节</a>)的数据库冲突。</p>
<p>代码 1.5 也修改了其他几行,将</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="c1"># Use SCSS for stylesheets</span>
<span class="n">gem</span> <span class="s1">'sass-rails'</span><span class="p">,</span> <span class="s1">'~> 4.0.1'</span>
<span class="c1"># Use Uglifier as compressor for JavaScript assets</span>
<span class="n">gem</span> <span class="s1">'uglifier'</span><span class="p">,</span> <span class="s1">'>= 1.3.0'</span>
<span class="c1"># Use CoffeeScript for .js.coffee assets and views</span>
<span class="n">gem</span> <span class="s1">'coffee-rails'</span><span class="p">,</span> <span class="s1">'~> 4.0.0'</span>
</pre></div>
</div>
<p>改成了</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">gem</span> <span class="s1">'sass-rails'</span><span class="p">,</span> <span class="s1">'4.0.1'</span>
<span class="n">gem</span> <span class="s1">'uglifier'</span><span class="p">,</span> <span class="s1">'2.1.1'</span>
<span class="n">gem</span> <span class="s1">'coffee-rails'</span><span class="p">,</span> <span class="s1">'4.0.1'</span>
</pre></div>
</div>
<p>如下的代码</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">gem</span> <span class="s1">'uglifier'</span><span class="p">,</span> <span class="s1">'>=1.3.0'</span>
</pre></div>
</div>
<p>会安装 <code>1.3.0</code> 或以上的最新版 <code>uglifier</code> gem(在 asset pipeline 中处理文件的压缩),当然也可以安装 <code>7.2</code> 版。而下面的代码</p>
<div class="codeblock"><div class="highlight type-ruby"><pre><span class="n">gem</span> <span class="s1">'coffee-rails'</span><span class="p">,</span> <span class="s1">'~> 4.0.0'</span>
</pre></div>
</div>
<p>只会安装高于 <code>4.0.0</code> 版的 <code>coffee-rails</code>(也是 asset pipeline 用到的)。换句话说,<code>>=</code> 总会升级到最新版;<code>~> 4.0.0</code> 只会升级补丁版本的更新(例如从 <code>4.0.0</code> 到 <code>4.0.1</code>),而不会升级到次版本或主版本的更新(例如从 <code>4.0</code> 到 <code>4.1</code>)。不过,经验告诉我们,即使是补丁版本的升级也可能会产生错误,所以在本教程中我们基本上会为所有的 gem 指定明确的版本号。你可以使用任何 gem 的最新版本,还可以在 <code>Gemfile</code> 中使用 <code>~></code>(推荐高级用户使用),但我事先提醒你,这可能会导致本教程开发的程序表现异常。</p>
<p>修改完 <code>Gemfile</code> 后,运行 <code>bundle update</code><sup class="footnote" id="fnref-1-16"><a href="#fn-1-16" rel="footnote">10</a></sup> 和 <code>bundle install</code> 安装所需的 gem:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>bundle update
<span class="gp">$ </span>bundle install
Fetching <span class="nb">source </span>index <span class="k">for </span>https://rubygems.org/
.
.
.
</pre></div>
</div>
<p><code>bundle install</code> 命令会花费一点时间,一旦结束我们的程序就可以运行了。</p>
<h3 id='section-1-2-5'><span>1.2.5</span> rails server</h3>
<p>运行完 <a href="chapter1.html#section-1-2-3">1.2.3 节</a>中介绍的 <code>rails new</code> 和 <a href="chapter1.html#section-1-2-4">1.2.4 节</a> 中介绍的 <code>bundle install</code> 后我们的程序就可以运行了,但怎么运行呢?Rails 自带了一个命令行程序可以在开发电脑上运行一个本地服务器:<sup class="footnote" id="fnref-1-5"><a href="#fn-1-5" rel="footnote">11</a></sup></p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>rails server
<span class="gp">=> </span>Booting WEBrick
<span class="gp">=> </span>Rails application starting on http://0.0.0.0:3000
<span class="gp">=> </span>Call with -d to detach
<span class="gp">=> </span>Ctrl-C to shutdown server
</pre></div>
</div>
<p>(如果系统提示缺少 JavaScript 运行时,请浏览 <a href="https://github.com/sstephenson/execjs">execjs 位于 github 的页面</a>查看一些可选的运行时,我建议安装 <a href="http://nodejs.org/">Node.js</a>。)上述代码的提示信息告诉我们这个应用程序在 <code>0.0.0.0</code> 地址的 3000<sup class="footnote" id="fnref-1-6"><a href="#fn-1-6" rel="footnote">12</a></sup> 端口运行。这个地址告诉系统监听这台电脑上的每一个可用的 IP 地址。一般来说,我们可以通过一个特殊的地址 <code>127.0.0.1</code> 来查看应用程序,或者也可以使用 <code>localhost</code>。通过 <a href="http://localhost:3000">http://localhost:3000</a> 查看结果,如图 1.3 所示。</p>
<div class="figure" id="figure-1-3">
<img src="figures/riding_rails_4_0.png" alt="riding rails40" />
<p class="caption"><span>图 1.3:</span>默认的 Rails 页面</p>
</div>
<p>点击“About your application’s environment” 可以查看应用程序的信息。结果如图 1.4 所示。(图 1.4 显示的是截图时我电脑上的环境信息,你的结果可能会与我的不同。)</p>
<p>当然我们不是真的想使用默认的 Rails 页面,但这个页面告诉我们 Rails 可以正常运行了。我们会在 <a href="chapter5.html#section-5-3-2">5.3.2 节</a>中移除默认页面。</p>
<div class="figure" id="figure-1-4">
<img src="figures/riding_rails_environment_4_0.png" alt="riding rails environment 40" />
<p class="caption"><span>图 1.4:</span>默认页面中的应用程序信息</p>
</div>
<h3 id='section-1-2-6'><span>1.2.6</span> 模型-视图-控制器(MVC)</h3>
<p>在初期阶段,概览一下 Rails 程序的工作方式(如图 1.5)多少是会有些帮助的。你可能已经注意到了,在 Rails 应用程序的文件结构(如图 1.2)中有一个文件夹叫 <code>app/</code>,其中有三个子文件夹:<code>models</code>、<code>views</code> 和 <code>controllers</code>。这暗示 Rails 采用了 MVC 架构模式,这种模式强制地将“域逻辑(domain logic)”(也叫“业务逻辑(business logic)”)和图形用户界面(GUI)的输入、表现逻辑分开。在 Web 应用程序中,“域逻辑”的典型代表是“用户(users)”、“文章(articles)”和“产品(products)”等数据模型,GUI 则是浏览器中的网页。</p>
<p>在 Rails 交互中,浏览器发送一个请求(request),网络服务器收到请求将其传送到 Rails 的控制器,然后决定下一步做什么。某些情况下,控制器会立即渲染视图(view)模板,生成 HTML 然后将结果发送回浏览器。对于动态网站来说,控制器会和模型(model)交互。模型是一个 Ruby 对象,表示网站中的一个元素(例如一个用户),并且负责和数据库通信。调用模型后,控制器再渲染视图并将生成的 HTML 代码返回给浏览器。</p>
<p>如果你觉得这些内容有点抽象,不用担心,后面会经常讲到 MVC。在 <a href="chapter2.html#section-2-2-2">2.2.2 节</a> 中会以演示程序为例较为深入的讨论 MVC;在后面的大型示例程序中会使用 MVC 的全部内容,<a href="chapter3.html#section-3-1-2">3.1.2 节</a> 将介绍控制器和视图,<a href="chapter6.html#section-6-1">6.1 节</a>将介绍模型,<a href="chapter7.html#section-7-1-2">7.1.2 节</a>中将把三个部分放在一起使用。</p>
<h2 id='section-1-3'><span>1.3</span> 用 git 做版本控制</h2>
<p>我们已经创建了一个可以运行的 Rails 应用程序,接下来要花点时间来做一件事,虽然不是必须做的,但是很多 Rails 开发者基本上都认为这是应该做的最基本的事情,这件事就是将应用程序的源代码放入版本控制系统中。版本控制系统可以跟踪项目代码的变化,便于和他人协作,如果出现问题(例如不小心删除了文件)还可以回滚到以前的版本。每个软件开发者都应该学习使用版本控制系统。</p>
<p>版本控制工具很多,Rails 社区更多的会使用 <a href="http://git-scm.com/">git</a>,它最初是由 Linus Torvalds 开发用来存储 Linux 内核代码的。git 的知识很多,这里我们只会介绍一些简单的内容,网络上有很多免费的资料可以阅读,我特别推荐 Scott Chacon 的《<a href="http://git-scm.com/book">Pro Git</a>》(Apress 2009 年出版。<a href="http://git-scm.com/book/zh">中文版</a>)。之所以推荐你将代码放到 git 这个版本控制系统中是因为这几乎是 Rails 社区的普遍做法,还因为这样做更利于代码的分享(<a href="chapter1.html#section-1-3-4">1.3.4 节</a>),也便于程序的部署(<a href="chapter1.html#section-1-4">1.4 节</a>)。</p>
<div class="figure" id="figure-1-5">
<img src="figures/mvc_schematic.png" alt="mvc schematic" />
<p class="caption"><span>图 1.5:</span>MVC 架构的图解</p>
</div>
<h3 id='section-1-3-1'><span>1.3.1</span> 安装与设置</h3>
<p>如果你还没安装 git,请按照前面的介绍进行安装。(如前所述,安装的过程可以参考《Pro Git》书中的“<a href="http://git-scm.com/book/en/Getting-Started-Installing-Git">安装 Git</a>”一节。)</p>
<h4 id='section-1-3-1-1'><span></span>第一次运行时的设置</h4>
<p>安装 git 后,你应该做一些只需做一次的事情:系统设置——这样的设置在每台电脑上只需做一次:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git config --global user.name <span class="s2">"Your Name"</span>
<span class="gp">$ </span>git config --global user.email [email protected]
</pre></div>
</div>
<p>我还想用 <code>co</code> 代替字数较多的 <code>checkout</code> 命令,那么要做如下设置:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git config --global alias.co checkout
</pre></div>
</div>
<p>本书中我基本上都会使用完整的 <code>checkout</code> 命令,防止你没有做以上的设置,但我自己都是使用 <code>git co</code>。</p>
<p>最后,你还可以设置编辑 git 提交信息时使用的编辑器。如果你使用的是图形界面的编辑器,例如 Sublime Text、TextMate、gVim 或 MacVim,要加上一个旗标确保编辑器会在终端中保持状态而不是立马结束命令:<sup class="footnote" id="fnref-1-7"><a href="#fn-1-7" rel="footnote">13</a></sup></p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git config --global core.editor <span class="s2">"subl -w"</span>
</pre></div>
</div>
<p>如果使用其他编辑器,请使用以下代码替换 <code>subl -w</code>:TextMate 用 <code>mate -w</code>,gVim 用 <code>gvim -f</code>,MacVim 用 <code>mvim -f</code>。</p>
<h4 id='section-1-3-1-2'><span></span>设置第一个仓库</h4>
<p>下面的步骤你每次新建一个仓库时都要执行。首先进入刚创建的应用程序的根目录,然后初始化一个新仓库:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git init
Initialized empty Git repository <span class="k">in</span> /Users/mhartl/rails_projects/first_app/.git/
</pre></div>
</div>
<p>接下来要将项目的文件添加到仓库中。不过有一点要说明一下:git 默认会跟踪所有文件的变化,但是有些文件我们并不想跟踪。例如,Rails 会创建一些日志文件记录应用程序的动作,这些文件经常变化,我们并不需要版本控制系统跟踪这些文件。git 有忽略文件的机制:在应用程序的根目录创建一个名为 <code>.gitignore</code> 的文件,然后写入一些规则告诉 git 要忽略哪些文件即可。<sup class="footnote" id="fnref-1-8"><a href="#fn-1-8" rel="footnote">14</a></sup></p>
<p>看一下前面的表格 1.1,<code>rails</code> 命令默认会在应用程序的根目录创建 <code>.gitignore</code> 文件,其内容如代码 1.6 所示。</p>
<div class="codeblock has-caption" id="codeblock-1-6"><p class="caption"><span>代码 1.6:</span><code>rails</code> 命令默认创建的 <code>.gitignore</code> 文件</p><div class="highlight type-plaintext"><pre># See http://help.github.com/ignore-files/ for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
</pre></div>
</div>
<p>代码 1.6 中的代码会让 git 忽略日志文件,Rails 的临时文件(<code>tmp/</code>)和 SQLite 数据库。(为了忽略 <code>log/</code> 文件夹中的日志文件,我们用 <code>log/*.log</code> 来忽略所有以 <code>.log</code> 结尾的文件)大部分被忽略的文件都是变动频繁,而且是自动创建的,没必要把这些文件纳入版本控制。而且,当和他人协作时这些文件还可能会导致冲突。</p>
<p>代码 1.6 中的代码只是针对本教程的,但是系统中的一些文件也要忽略,代码 1.7 则更为全面。增强后的 <code>.gitignore</code> 文件会忽略 Rails 应用程序的文档、Vim 和 Emacs 的交换文件(swap file),以及 Mac Finder 程序生成的诡异的 <code>.DS_Store</code> 文件(针对 OS X 用户)。如果你想使用这个更全面的忽略文件,用你喜好的文本编辑器打开 <code>.gitignore</code> 文件,然后写入代码 1.7 中的代码。</p>
<div class="codeblock has-caption" id="codeblock-1-7"><p class="caption"><span>代码 1.7:</span>加强版 <code>.gitignore</code> 文件</p><div class="highlight type-plaintext"><pre># Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
# Ignore other unneeded files.
database.yml
doc/
*.swp
*~
.project
.DS_Store
.idea
.secret
</pre></div>
</div>
<h3 id='section-1-3-2'><span>1.3.2</span> 添加文件并提交</h3>
<p>最后我们要把 Rails 项目中的文件添加到 git 中,然后提交结果。你可以使用下述命令添加所有的文件(除了 <code>.gitignore</code> 中忽略的文件):</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git add .
</pre></div>
</div>
<p>这里的点号(.)代表当前目录,git 会自动的将所有的文件,包括子目录中的文件添加到 git 中。这个命令会将项目的文件添加到暂存区域(staging area),这个区域包含未提交的改动。你可以使用 <code>status</code> 命令查看暂存区域有哪些文件:<sup class="footnote" id="fnref-1-9"><a href="#fn-1-9" rel="footnote">15</a></sup></p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git status
<span class="c"># On branch master</span>
<span class="c">#</span>
<span class="c"># Initial commit</span>
<span class="c">#</span>
<span class="c"># Changes to be committed:</span>
<span class="c"># (use "git rm --cached <file>..." to unstage)</span>
<span class="c">#</span>
<span class="c"># new file: README.rdoc</span>
<span class="c"># new file: Rakefile</span>
.
.
.
</pre></div>
</div>
<p>(显示的结果很长,所以我用点号代替了。)</p>
<p>用 <code>commit</code> 命令告诉 git 你想保存这些改动:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git commit -m <span class="s2">"Initial commit"</span>
<span class="o">[</span>master <span class="o">(</span>root-commit<span class="o">)</span> df0a62f] Initial commit
42 files changed, 8461 insertions<span class="o">(</span>+<span class="o">)</span>, 0 deletions<span class="o">(</span>-<span class="o">)</span>
create mode 100644 README.rdoc
create mode 100644 Rakefile
.
.
.
</pre></div>
</div>
<p>旗标 <code>-m</code> 允许你为这次提交添加一个信息,如果没有提供 <code>-m</code>,git 会打开你在 <a href="chapter1.html#section-1-3-1">1.3.1 节</a>中设置的编辑器,你需要在编辑器中填写信息。</p>
<p>有一点很重要,git 提交是针对本地的,数据只存在执行提交的电脑中。这一点和另一个很著名的开源版本控制系统 SVN 不同,SVN 提交时会更新远程仓库。git 将 SVN 中的提交分成了两部分:本地保存的更改(<code>git commit</code>)和将更改推送到远程仓库(<code>git push</code>)。在 <a href="chapter1.html#section-1-3-5">1.3.5 节</a>中会演示推送这一步。</p>
<p>顺便说一下,你可以使用 <code>log</code> 命令查看提交的历史信息:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git log
commit df0a62f3f091e53ffa799309b3e32c27b0b38eb4
Author: Michael Hartl <[email protected]>
Date: Thu Oct 15 11:36:21 2009 -0700
Initial commit
</pre></div>
</div>
<p>如果要退出 <code>git log</code>,输入 <code>q</code>。</p>
<h3 id='section-1-3-3'><span>1.3.3</span> git 为我们带来了什么好处?</h3>
<p>现在你可能还不是完全清楚将源码纳入版本控制系统有什么好处,那我就举个例子来说明一下吧。(后续章节中还有很多例子)假设你不小心做了一些改动,比如说删除了 <code>app/controllers/</code> 文件夹:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>ls app/controllers/
application_controller.rb
<span class="gp">$ </span>rm -rf app/controllers/
<span class="gp">$ </span>ls app/controllers/
ls: app/controllers/: No such file or directory
</pre></div>
</div>
<p>我们用 Unix 中的 <code>ls</code> 命令列出 <code>app/controllers/</code> 文件夹中的内容,用 <code>rm</code> 命令删除这个文件夹。旗标 <code>-rf</code> 的意思是“强制递归”,无需得到确认就递归的删除所有文件、文件夹、子文件夹等。</p>
<p>查看一下状态看看发生了什么:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git status
<span class="c"># On branch master</span>
<span class="c"># Changed but not updated:</span>
<span class="c"># (use "git add/rm <file>..." to update what will be committed)</span>
<span class="c"># (use "git checkout -- <file>..." to discard changes in working directory)</span>
<span class="c">#</span>
<span class="c"># deleted: app/controllers/application_controller.rb</span>
<span class="c">#</span>
no changes added to commit <span class="o">(</span>use <span class="s2">"git add"</span> and/or <span class="s2">"git commit -a"</span><span class="o">)</span>
</pre></div>
</div>
<p>可以看到一个文件被删除了,但是这个改动只发生在工作区,还没有提交。这样我们就可以使用 <code>checkout</code> 命令切换到前一个提交记录来撤销这次改动(其中旗标 <code>-f</code> 意思是覆盖当前的改动):</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git checkout -f
<span class="gp">$ </span>git status
<span class="c"># On branch master</span>
nothing to commit <span class="o">(</span>working directory clean<span class="o">)</span>
<span class="gp">$ </span>ls app/controllers/
application_controller.rb
</pre></div>
</div>
<p>删除的文件夹和文件又回来了,这下放心了!</p>
<h3 id='section-1-3-4'><span>1.3.4</span> GitHub</h3>
<p>你已经将项目的代码纳入 git 版本控制系统了,现在可以将其推送到 GitHub 了。GitHub 是一个针对 Git 仓库的存储及分享社交平台。将代码的拷贝存一份在 GitHub 有两个目的:其一是对代码的完整备份(包括完整的提交历史),其二是方便以后的协作。这一步不是必须要做的,不过加入 GitHub 可以给你提供机会参与到更广为人知的开源项目中。</p>
<p>GitHub 有一些收费的计划,但是对开源项目的代码是免费的,如果你还没有 GitHub 的账户就赶快注册一个<a href="https://github.com/signup/free">免费的账户</a>吧。(或许你先要参考 GitHub 的“<a href="https://help.github.com/articles/generating-ssh-keys">创建 SSH 密匙</a>”一文)注册后,点击创建仓库的链接(<a href="https://github.com/repositories/new">New repository</a>),然后填入所需的信息,如图 1.6 所示。(注意,不要选择使用 <code>README</code> 文件初始化仓库(Initialize this repository with a README),因为 <code>rails new</code> 已经自动创建了这个文件。)提交表单后,按照下面的方法将你第一个应用程序推送上去:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git remote add origin [email protected]:<username>/first_app.git
<span class="gp">$ </span>git push -u origin master
</pre></div>
</div>
<div class="figure" id="figure-1-6">
<img src="figures/create_first_repository_4_0.png" alt="create first repository 40" />
<p class="caption"><span>图 1.6:</span>在 GitHub 创建第一个仓库</p>
</div>
<p>上面的代码告诉 Git 你要添加 GitHub 上面的仓库地址为代码的原本,代表本地的主分支(<code>master</code>),然后将本地的仓库推送到 GitHub 上。(先不要关心旗标 <code>-u</code> 的作用,如果你实在好奇可以搜索“git set upstream”。)当然你要把 <code><username></code> 换成你真正的用户名。例如,我执行的命令是:</p>
<div class="codeblock"><div class="highlight type-shell"><pre><span class="gp">$ </span>git remote add origin https://github.com/mhartl/first_app.git