-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathactive_record_basics.html
508 lines (466 loc) · 29.3 KB
/
active_record_basics.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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Active Record 基础 — Ruby on Rails 指南</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print" />
<link rel="stylesheet" type="text/css" href="stylesheets/syntaxhighlighter/shCore.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/syntaxhighlighter/shThemeRailsGuides.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/fixes.css" />
<link href="images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body class="guide">
<div id="topNav">
<div class="wrapper">
<strong class="more-info-label">更多内容 <a href="http://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="http://rubyonrails.org/">综览</a></li>
<li class="more-info"><a href="http://rubyonrails.org/download">下载</a></li>
<li class="more-info"><a href="http://rubyonrails.org/deploy">部署</a></li>
<li class="more-info"><a href="https://github.com/rails/rails">源码</a></li>
<li class="more-info"><a href="http://rubyonrails.org/screencasts">视频</a></li>
<li class="more-info"><a href="http://rubyonrails.org/documentation">文件</a></li>
<li class="more-info"><a href="http://rubyonrails.org/community">社群</a></li>
<li class="more-info"><a href="http://weblog.rubyonrails.org/">Blog</a></li>
</ul>
</div>
</div>
<div id="header">
<div class="wrapper clearfix">
<h1><a href="index.html" title="回首页">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 />
<dl class="L">
<dt>入门</dt>
<dd><a href="getting_started.html">Rails 入门</a></dd>
<dt>模型</dt>
<dd><a href="active_record_basics.html">Active Record 基础</a></dd>
<dd><a href="active_record_migrations.html">Active Record 数据库迁移</a></dd>
<dd><a href="active_record_validations.html">Active Record 数据验证</a></dd>
<dd><a href="active_record_callbacks.html">Active Record 回调</a></dd>
<dd><a href="association_basics.html">Active Record 关联</a></dd>
<dd><a href="active_record_querying.html">Active Record 查询</a></dd>
<dt>视图</dt>
<dd><a href="layouts_and_rendering.html">Rails 布局和视图渲染</a></dd>
<dd><a href="form_helpers.html">Action View 表单帮助方法</a></dd>
<dt>控制器</dt>
<dd><a href="action_controller_overview.html">Action Controller 简介</a></dd>
<dd><a href="routing.html">Rails 路由全解</a></dd>
</dl>
<dl class="R">
<dt>深入</dt>
<dd><a href="active_support_core_extensions.html">Active Support 核心扩展</a></dd>
<dd><a href="i18n.html">Rails 国际化 API</a></dd>
<dd><a href="action_mailer_basics.html">Action Mailer 基础</a></dd>
<dd><a href="active_job_basics.html">Active Job 基础</a></dd>
<dd><a href="security.html">Rails 安全指南</a></dd>
<dd><a href="debugging_rails_applications.html">调试 Rails 程序</a></dd>
<dd><a href="configuring.html">设置 Rails 程序</a></dd>
<dd><a href="command_line.html">Rails 命令行</a></dd>
<dd><a href="asset_pipeline.html">Asset Pipeline</a></dd>
<dd><a href="working_with_javascript_in_rails.html">在 Rails 中使用 JavaScript</a></dd>
<dd><a href="constant_autoloading_and_reloading.html">Constant Autoloading and Reloading</a></dd>
<dt>扩展 Rails</dt>
<dd><a href="rails_on_rack.html">Rails on Rack</a></dd>
<dd><a href="generators.html">客制与新建 Rails 产生器</a></dd>
<dd><a href="rails_application_templates.html">Rails 应用程式模版</a></dd>
<dt>贡献 Ruby on Rails</dt>
<dd><a href="contributing_to_ruby_on_rails.html">贡献 Ruby on Rails</a></dd>
<dd><a href="api_documentation_guidelines.html">API 文件准则</a></dd>
<dd><a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南准则</a></dd>
<dt>维护方针</dt>
<dd><a href="maintenance_policy.html">维护方针</a></dd>
<dt>发布记</dt>
<dd><a href="upgrading_ruby_on_rails.html">升级 Ruby on Rails</a></dd>
<dd><a href="4_2_release_notes.html">Ruby on Rails 4.2 发布记</a></dd>
<dd><a href="4_1_release_notes.html">Ruby on Rails 4.1 发布记</a></dd>
<dd><a href="4_0_release_notes.html">Ruby on Rails 4.0 发布记</a></dd>
<dd><a href="3_2_release_notes.html">Ruby on Rails 3.2 发布记</a></dd>
<dd><a href="3_1_release_notes.html">Ruby on Rails 3.1 发布记</a></dd>
<dd><a href="3_0_release_notes.html">Ruby on Rails 3.0 发布记</a></dd>
<dd><a href="2_3_release_notes.html">Ruby on Rails 2.3 发布记</a></dd>
<dd><a href="2_2_release_notes.html">Ruby on Rails 2.2 发布记</a></dd>
</dl>
</div>
</li>
<!-- <li><a class="nav-item" href="//github.com/docrails-tw/wiki">参与翻译</a></li> -->
<li><a class="nav-item" href="https://github.com/ruby-china/guides/blob/master/CONTRIBUTING.md">贡献</a></li>
<li><a class="nav-item" href="credits.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">Rails 入门</option>
</optgroup>
<optgroup label="模型">
<option value="active_record_basics.html">Active Record 基础</option>
<option value="active_record_migrations.html">Active Record 数据库迁移</option>
<option value="active_record_validations.html">Active Record 数据验证</option>
<option value="active_record_callbacks.html">Active Record 回调</option>
<option value="association_basics.html">Active Record 关联</option>
<option value="active_record_querying.html">Active Record 查询</option>
</optgroup>
<optgroup label="视图">
<option value="layouts_and_rendering.html">Rails 布局和视图渲染</option>
<option value="form_helpers.html">Action View 表单帮助方法</option>
</optgroup>
<optgroup label="控制器">
<option value="action_controller_overview.html">Action Controller 简介</option>
<option value="routing.html">Rails 路由全解</option>
</optgroup>
<optgroup label="深入">
<option value="active_support_core_extensions.html">Active Support 核心扩展</option>
<option value="i18n.html">Rails 国际化 API</option>
<option value="action_mailer_basics.html">Action Mailer 基础</option>
<option value="active_job_basics.html">Active Job 基础</option>
<option value="security.html">Rails 安全指南</option>
<option value="debugging_rails_applications.html">调试 Rails 程序</option>
<option value="configuring.html">设置 Rails 程序</option>
<option value="command_line.html">Rails 命令行</option>
<option value="asset_pipeline.html">Asset Pipeline</option>
<option value="working_with_javascript_in_rails.html">在 Rails 中使用 JavaScript</option>
<option value="constant_autoloading_and_reloading.html">Constant Autoloading and Reloading</option>
</optgroup>
<optgroup label="扩展 Rails">
<option value="rails_on_rack.html">Rails on Rack</option>
<option value="generators.html">客制与新建 Rails 产生器</option>
<option value="rails_application_templates.html">Rails 应用程式模版</option>
</optgroup>
<optgroup label="贡献 Ruby on Rails">
<option value="contributing_to_ruby_on_rails.html">贡献 Ruby on Rails</option>
<option value="api_documentation_guidelines.html">API 文件准则</option>
<option value="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南准则</option>
</optgroup>
<optgroup label="维护方针">
<option value="maintenance_policy.html">维护方针</option>
</optgroup>
<optgroup label="发布记">
<option value="upgrading_ruby_on_rails.html">升级 Ruby on Rails</option>
<option value="4_2_release_notes.html">Ruby on Rails 4.2 发布记</option>
<option value="4_1_release_notes.html">Ruby on Rails 4.1 发布记</option>
<option value="4_0_release_notes.html">Ruby on Rails 4.0 发布记</option>
<option value="3_2_release_notes.html">Ruby on Rails 3.2 发布记</option>
<option value="3_1_release_notes.html">Ruby on Rails 3.1 发布记</option>
<option value="3_0_release_notes.html">Ruby on Rails 3.0 发布记</option>
<option value="2_3_release_notes.html">Ruby on Rails 2.3 发布记</option>
<option value="2_2_release_notes.html">Ruby on Rails 2.2 发布记</option>
</optgroup>
</select>
</li>
</ul>
</div>
</div>
</div>
<hr class="hide" />
<div id="feature">
<div class="wrapper">
<h2>Active Record 基础</h2><p>本文介绍 Active Record。</p><p>读完本文,你将学到:</p>
<ul>
<li>对象关系映射(Object Relational Mapping,ORM)和 Active Record 是什么,以及如何在 Rails 中使用;</li>
<li>Active Record 在 MVC 中的作用;</li>
<li>如何使用 Active Record 模型处理保存在关系型数据库中的数据;</li>
<li>Active Record 模式(schema)命名约定;</li>
<li>数据库迁移,数据验证和回调;</li>
</ul>
<div id="subCol">
<h3 class="chapter"><img src="images/chapters_icon.gif" alt="" />Chapters</h3>
<ol class="chapters">
<li>
<a href="#active-record-%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F">Active Record 是什么?</a>
<ul>
<li><a href="#active-record-%E6%A8%A1%E5%BC%8F">Active Record 模式</a></li>
<li><a href="#%E5%AF%B9%E8%B1%A1%E5%85%B3%E7%B3%BB%E6%98%A0%E5%B0%84">对象关系映射</a></li>
<li><a href="#active-record-%E7%94%A8%E4%BD%9C-orm-%E6%A1%86%E6%9E%B6">Active Record 用作 ORM 框架</a></li>
</ul>
</li>
<li>
<a href="#active-record-%E4%B8%AD%E7%9A%84%E2%80%9C%E5%A4%9A%E7%BA%A6%E5%AE%9A%E5%B0%91%E9%85%8D%E7%BD%AE%E2%80%9D%E5%8E%9F%E5%88%99">Active Record 中的“多约定少配置”原则</a>
<ul>
<li><a href="#%E5%91%BD%E5%90%8D%E7%BA%A6%E5%AE%9A">命名约定</a></li>
<li><a href="#%E6%A8%A1%E5%BC%8F%E7%BA%A6%E5%AE%9A">模式约定</a></li>
</ul>
</li>
<li><a href="#%E5%88%9B%E5%BB%BA-active-record-%E6%A8%A1%E5%9E%8B">创建 Active Record 模型</a></li>
<li><a href="#%E4%B8%8D%E7%94%A8%E9%BB%98%E8%AE%A4%E7%9A%84%E5%91%BD%E5%90%8D%E7%BA%A6%E5%AE%9A">不用默认的命名约定</a></li>
<li>
<a href="#crud%EF%BC%9A%E8%AF%BB%E5%86%99%E6%95%B0%E6%8D%AE">CRUD:读写数据</a>
<ul>
<li><a href="#%E5%88%9B%E5%BB%BA">创建</a></li>
<li><a href="#%E8%AF%BB%E5%8F%96">读取</a></li>
<li><a href="#%E6%9B%B4%E6%96%B0">更新</a></li>
<li><a href="#%E5%88%A0%E9%99%A4">删除</a></li>
</ul>
</li>
<li><a href="#%E6%95%B0%E6%8D%AE%E9%AA%8C%E8%AF%81">数据验证</a></li>
<li><a href="#%E5%9B%9E%E8%B0%83">回调</a></li>
<li><a href="#%E8%BF%81%E7%A7%BB">迁移</a></li>
</ol>
</div>
</div>
</div>
<div id="container">
<div class="wrapper">
<div id="mainCol">
<h3 id="active-record-是什么?">1 Active Record 是什么?</h3><p>Active Record 是 <a href="getting_started.html#the-mvc-architecture">MVC</a> 中的 M(模型),处理数据和业务逻辑。Active Record 负责创建和使用需要持久存入数据库中的数据。Active Record 实现了 Active Record 模式,是一种对象关系映射系统。</p><h4 id="active-record-模式">1.1 Active Record 模式</h4><p>Active Record 模式出自 <a href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">Martin Fowler</a> 的《企业应用架构模式》一书。在 Active Record 模式中,对象中既有持久存储的数据,也有针对数据的操作。Active Record 模式把数据存取逻辑作为对象的一部分,处理对象的用户知道如何把数据写入数据库,以及从数据库中读出数据。</p><h4 id="对象关系映射">1.2 对象关系映射</h4><p>对象关系映射(ORM)是一种技术手段,把程序中的对象和关系型数据库中的数据表连接起来。使用 ORM,程序中对象的属性和对象之间的关系可以通过一种简单的方法从数据库获取,无需直接编写 SQL 语句,也不过度依赖特定的数据库种类。</p><h4 id="active-record-用作-orm-框架">1.3 Active Record 用作 ORM 框架</h4><p>Active Record 提供了很多功能,其中最重要的几个如下:</p>
<ul>
<li>表示模型和其中的数据;</li>
<li>表示模型之间的关系;</li>
<li>通过相关联的模型表示继承关系;</li>
<li>持久存入数据库之前,验证模型;</li>
<li>以面向对象的方式处理数据库操作;</li>
</ul>
<h3 id="active-record-中的“多约定少配置”原则">2 Active Record 中的“多约定少配置”原则</h3><p>使用其他编程语言或框架开发程序时,可能必须要编写很多配置代码。大多数的 ORM 框架都是这样。但是,如果遵循 Rails 的约定,创建 Active Record 模型时不用做多少配置(有时甚至完全不用配置)。Rails 的理念是,如果大多数情况下都要使用相同的方式配置程序,那么就应该把这定为默认的方法。所以,只有常规的方法无法满足要求时,才要额外的配置。</p><h4 id="命名约定">2.1 命名约定</h4><p>默认情况下,Active Record 使用一些命名约定,查找模型和数据表之间的映射关系。Rails 把模型的类名转换成复数,然后查找对应的数据表。例如,模型类名为 <code>Book</code>,数据表就是 <code>books</code>。Rails 提供的单复数变形功能很强大,常见和不常见的变形方式都能处理。如果类名由多个单词组成,应该按照 Ruby 的约定,使用驼峰式命名法,这时对应的数据表将使用下划线分隔各单词。因此:</p>
<ul>
<li>数据表名:复数,下划线分隔单词(例如 <code>book_clubs</code>)</li>
<li>模型类名:单数,每个单词的首字母大写(例如 <code>BookClub</code>)</li>
</ul>
<table>
<thead>
<tr>
<th>模型 / 类</th>
<th>数据表 / 模式</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Post</code></td>
<td><code>posts</code></td>
</tr>
<tr>
<td><code>LineItem</code></td>
<td><code>line_items</code></td>
</tr>
<tr>
<td><code>Deer</code></td>
<td><code>deers</code></td>
</tr>
<tr>
<td><code>Mouse</code></td>
<td><code>mice</code></td>
</tr>
<tr>
<td><code>Person</code></td>
<td><code>people</code></td>
</tr>
</tbody>
</table>
<h4 id="模式约定">2.2 模式约定</h4><p>根据字段的作用不同,Active Record 对数据表中的字段命名也做了相应的约定:</p>
<ul>
<li>
<strong>外键</strong> - 使用 <code>singularized_table_name_id</code> 形式命名,例如 <code>item_id</code>,<code>order_id</code>。创建模型关联后,Active Record 会查找这个字段;</li>
<li>
<strong>主键</strong> - 默认情况下,Active Record 使用整数字段 <code>id</code> 作为表的主键。使用 <a href="%7B%7B%20site.baseurl%7D%7D/migrations.html">Active Record 迁移</a>创建数据表时,会自动创建这个字段;</li>
</ul>
<p>还有一些可选的字段,能为 Active Record 实例添加更多的功能:</p>
<ul>
<li>
<code>created_at</code> - 创建记录时,自动设为当前的时间戳;</li>
<li>
<code>updated_at</code> - 更新记录时,自动设为当前的时间戳;</li>
<li>
<code>lock_version</code> - 在模型中添加<a href="http://api.rubyonrails.org/classes/ActiveRecord/Locking.html">乐观锁定</a>功能;</li>
<li>
<code>type</code> - 让模型使用<a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Single+table+inheritance">单表继承</a>;</li>
<li>
<code>(association_name)_type</code> - <a href="association_basics.html#polymorphic-associations">多态关联</a>的类型;</li>
<li>
<code>(table_name)_count</code> - 缓存关联对象的数量。例如,<code>posts</code> 表中的 <code>comments_count</code> 字段,缓存每篇文章的评论数;</li>
</ul>
<div class="note"><p>虽然这些字段是可选的,但在 Active Record 中是被保留的。如果想使用相应的功能,就不要把这些保留字段用作其他用途。例如,<code>type</code> 这个保留字段是用来指定数据表使用“单表继承”(STI)的,如果不用 STI,请使用其他的名字,例如“context”,这也能表明该字段的作用。</p></div><h3 id="创建-active-record-模型">3 创建 Active Record 模型</h3><p>创建 Active Record 模型的过程很简单,只要继承 <code>ActiveRecord::Base</code> 类就行了:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class Product < ActiveRecord::Base
end
</pre>
</div>
<p>上面的代码会创建 <code>Product</code> 模型,对应于数据库中的 <code>products</code> 表。同时,<code>products</code> 表中的字段也映射到 <code>Product</code> 模型实例的属性上。假如 <code>products</code> 表由下面的 SQL 语句创建:</p><div class="code_container">
<pre class="brush: sql; gutter: false; toolbar: false">
CREATE TABLE products (
id int(11) NOT NULL auto_increment,
name varchar(255),
PRIMARY KEY (id)
);
</pre>
</div>
<p>按照这样的数据表结构,可以编写出下面的代码:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
p = Product.new
p.name = "Some Book"
puts p.name # "Some Book"
</pre>
</div>
<h3 id="不用默认的命名约定">4 不用默认的命名约定</h3><p>如果想使用其他的命名约定,或者在 Rails 程序中使用即有的数据库可以吗?没问题,不用默认的命名约定也很简单。</p><p>使用 <code>ActiveRecord::Base.table_name=</code> 方法可以指定数据表的名字:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class Product < ActiveRecord::Base
self.table_name = "PRODUCT"
end
</pre>
</div>
<p>如果这么做,还要在测试中调用 <code>set_fixture_class</code> 方法,手动指定固件(<code>class_name.yml</code>)的类名:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class FunnyJoke < ActiveSupport::TestCase
set_fixture_class funny_jokes: Joke
fixtures :funny_jokes
...
end
</pre>
</div>
<p>还可以使用 <code>ActiveRecord::Base.primary_key=</code> 方法指定数据表的主键:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class Product < ActiveRecord::Base
self.primary_key = "product_id"
end
</pre>
</div>
<h3 id="crud:读写数据">5 CRUD:读写数据</h3><p>CURD 是四种数据操作的简称:C 表示创建,R 表示读取,U 表示更新,D 表示删除。Active Record 自动创建了处理数据表中数据的方法。</p><h4 id="创建">5.1 创建</h4><p>Active Record 对象可以使用 Hash 创建,在块中创建,或者创建后手动设置属性。<code>new</code> 方法会实例化一个对象,<code>create</code> 方法实例化一个对象,并将其存入数据库。</p><p>例如,<code>User</code> 模型中有两个属性,<code>name</code> 和 <code>occupation</code>。调用 <code>create</code> 方法会实例化一个对象,并把该对象对应的记录存入数据库:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
user = User.create(name: "David", occupation: "Code Artist")
</pre>
</div>
<p>使用 <code>new</code> 方法,可以实例化一个对象,但不会保存:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
user = User.new
user.name = "David"
user.occupation = "Code Artist"
</pre>
</div>
<p>调用 <code>user.save</code> 可以把记录存入数据库。</p><p><code>create</code> 和 <code>new</code> 方法从结果来看,都实现了下面代码的功能:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
user = User.new do |u|
u.name = "David"
u.occupation = "Code Artist"
end
</pre>
</div>
<h4 id="读取">5.2 读取</h4><p>Active Record 为读取数据库中的数据提供了丰富的 API。下面举例说明。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# return a collection with all users
users = User.all
</pre>
</div>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# return the first user
user = User.first
</pre>
</div>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# return the first user named David
david = User.find_by(name: 'David')
</pre>
</div>
<div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
# find all users named David who are Code Artists and sort by created_at
# in reverse chronological order
users = User.where(name: 'David', occupation: 'Code Artist').order('created_at DESC')
</pre>
</div>
<p><a href="active_record_querying.html">Active Record 查询</a>一文会详细介绍查询 Active Record 模型的方法。</p><h4 id="更新">5.3 更新</h4><p>得到 Active Record 对象后,可以修改其属性,然后再存入数据库。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
user = User.find_by(name: 'David')
user.name = 'Dave'
user.save
</pre>
</div>
<p>还有个简写方式,使用 Hash,指定属性名和属性值,例如:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
user = User.find_by(name: 'David')
user.update(name: 'Dave')
</pre>
</div>
<p>一次更新多个属性时使用这种方法很方便。如果想批量更新多个记录,可以使用类方法 <code>update_all</code>:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
User.update_all "max_login_attempts = 3, must_change_password = 'true'"
</pre>
</div>
<h4 id="删除">5.4 删除</h4><p>类似地,得到 Active Record 对象后还可以将其销毁,从数据库中删除。</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
user = User.find_by(name: 'David')
user.destroy
</pre>
</div>
<h3 id="数据验证">6 数据验证</h3><p>在存入数据库之前,Active Record 还可以验证模型。模型验证有很多方法,可以检查属性值是否不为空、是否是唯一的,或者没有在数据库中出现过,等等。</p><p>把数据存入数据库之前进行验证是十分重要的步骤,所以调用 <code>create</code>、<code>save</code>、<code>update</code> 这三个方法时会做数据验证,验证失败时返回 <code>false</code>,此时不会对数据库做任何操作。这三个方法都有对应的爆炸方法(<code>create!</code>,<code>save!</code>,<code>update!</code>),爆炸方法要严格一些,如果验证失败,会抛出 <code>ActiveRecord::RecordInvalid</code> 异常。下面是个简单的例子:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class User < ActiveRecord::Base
validates :name, presence: true
end
User.create # => false
User.create! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
</pre>
</div>
<p><a href="active_record_validations.html">Active Record 数据验证</a>一文会详细介绍数据验证。</p><h3 id="回调">7 回调</h3><p>Active Record 回调可以在模型声明周期的特定事件上绑定代码,相应的事件发生时,执行这些代码。例如创建新纪录时,更新记录时,删除记录时,等等。<a href="active_record_callbacks.html">Active Record 回调</a>一文会详细介绍回调。</p><h3 id="迁移">8 迁移</h3><p>Rails 提供了一个 DSL 用来处理数据库模式,叫做“迁移”。迁移的代码存储在特定的文件中,通过 <code>rake</code> 调用,可以用在 Active Record 支持的所有数据库上。下面这个迁移会新建一个数据表:</p><div class="code_container">
<pre class="brush: ruby; gutter: false; toolbar: false">
class CreatePublications < ActiveRecord::Migration
def change
create_table :publications do |t|
t.string :title
t.text :description
t.references :publication_type
t.integer :publisher_id
t.string :publisher_type
t.boolean :single_issue
t.timestamps
end
add_index :publications, :publication_type_id
end
end
</pre>
</div>
<p>Rails 会跟踪哪些迁移已经应用到数据库中,还提供了回滚功能。创建数据表要执行 <code>rake db:migrate</code> 命令;回滚操作要执行 <code>rake db:rollback</code> 命令。</p><p>注意,上面的代码和具体的数据库种类无关,可用于 MySQL、PostgreSQL、Oracle 等数据库。关于迁移的详细介绍,参阅 <a href="active_record_migrations.html">Active Record 迁移</a>一文。</p>
<h3>反馈</h3>
<p>
欢迎帮忙改善指南质量。
</p>
<p>
如发现任何错误,欢迎修正。开始贡献前,可先行阅读<a href="http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#contributing-to-the-rails-documentation">贡献指南:文档</a>。
</p>
<p>翻译如有错误,深感抱歉,欢迎 <a href="https://github.com/ruby-china/guides/fork">Fork</a> 修正,或至此处<a href="https://github.com/ruby-china/guides/issues/new">回报</a>。</p>
<p>
文章可能有未完成或过时的内容。请先检查 <a href="http://edgeguides.rubyonrails.org">Edge Guides</a> 来确定问题在 master 是否已经修掉了。再上 master 补上缺少的文件。内容参考 <a href="ruby_on_rails_guides_guidelines.html">Ruby on Rails 指南准则</a>来了解行文风格。
</p>
<p>最后,任何关于 Ruby on Rails 文档的讨论,欢迎到 <a href="http://groups.google.com/group/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/">创用 CC 姓名标示-相同方式分享 4.0 国际授权条款</a>授权。</p>
<p>“Rails”、“Ruby on Rails”,以及 Rails logo 为 David Heinemeier Hansson 的商标。版权所有。</p>
</div>
</div>
<script type="text/javascript" src="javascripts/jquery.min.js"></script>
<script type="text/javascript" src="javascripts/responsive-tables.js"></script>
<script type="text/javascript" src="javascripts/guides.js"></script>
<script type="text/javascript" src="javascripts/syntaxhighlighter/shCore.js"></script>
<script type="text/javascript" src="javascripts/syntaxhighlighter/shBrushRuby.js"></script>
<script type="text/javascript" src="javascripts/syntaxhighlighter/shBrushXml.js"></script>
<script type="text/javascript" src="javascripts/syntaxhighlighter/shBrushSql.js"></script>
<script type="text/javascript" src="javascripts/syntaxhighlighter/shBrushPlain.js"></script>
<script type="text/javascript">
SyntaxHighlighter.all();
$(guidesIndex.bind);
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
// ga('create', '', 'ruby-china.github.io');
ga('require', 'displayfeatures');
ga('send', 'pageview');
</script>
</body>
</html>