Ruby on Rails - Active Record
Ruby on Rails - Active Record
Section titled “Ruby on Rails - Active Record”Active Record (活动记录) 是 MVC (模型-视图-控制器) 中的 M——模型层。它是 Rails 提供的对象关系映射 (ORM) 系统。Active Record 允许您像操作 Ruby 对象一样与数据库表进行交互,抽象掉了大部分 SQL 语句。
Active Record 的核心原则:
- 表映射到类:一个数据库表(例如,
books)对应一个 Ruby 类(例如,Book)。 - 行映射到对象:表中的每一行代表该类的一个实例(对象)。
- 列映射到对象属性:表中的列对应于对象的属性。
Active Record 提供了用于 CRUD (创建、读取、更新、删除) 操作的方法,以及定义模型之间的关联、验证、回调和数据库查询等。
将领域模型映射到数据库 Schema
Section titled “将领域模型映射到数据库 Schema”在为 Rails 应用程序设计数据库 schema (结构) 时,请遵循以下约定:
- 表命名:表名使用复数和小写(例如,
books,authors)。模型类名使用单数和驼峰命名法 (CamelCased)(例如,Book,Author)。 - 主键:每个表应有一个
id列作为其主键(默认为自增整数)。Active Record 会自动管理这一点。 - 外键:对于关联(例如,一本书属于一个作者),拥有
belongs_to关联的表(例如,books)将有一个外键列,其命名方式是关联模型的名称加上_id后缀(例如,author_id)。 - 时间戳:习惯上在表中包含
created_at和updated_at时间戳列。如果这些列存在,Active Record 会自动管理它们。
创建 Active Record 模型
Section titled “创建 Active Record 模型”您可以使用 Rails 生成器命令生成模型文件。对于我们的图书库应用程序,让我们创建 Book 和 Subject 模型。
$ bin/rails generate model Book title:string price:decimal subject:references description:text$ bin/rails generate model Subject name:string这个命令做了几件事:
- 创建模型文件:
app/models/book.rb和app/models/subject.rb。 - 在
db/migrate/中创建迁移文件,用于定义books和subjects表的 schema。Book 生成器中的subject:references会自动添加一个subject_id列,并在模型中建立belongs_to关联(如果可能)。 - 创建测试文件(例如,
test/models/book_test.rb)和 fixtures 文件。
生成的 app/models/book.rb 可能看起来像这样(如果 subject:references 有效使用了的话):
class Book < ApplicationRecord belongs_to :subject # Added by 'subject:references'end以及 app/models/subject.rb:
class Subject < ApplicationRecordend注意:模型现在继承自 ApplicationRecord,而 ApplicationRecord 本身继承自 ActiveRecord::Base。这为应用程序范围内的模型配置提供了一个通用位置。
定义关联 (Associations)
Section titled “定义关联 (Associations)”关联定义了模型之间的关系。常见的关联类型包括:
belongs_to:表示一对一或一对多连接,其中该模型拥有外键(例如,一个Book属于一个Subject)。has_many:表示一对多关系(例如,一个Subject有多本Book)。has_one:表示一对一关系(例如,一个User有一个Profile)。has_and_belongs_to_many(HABTM):用于使用连接表直接建立多对多关系。has_many :through:一种更灵活的建立多对多关系的方式,通常比 HABTM 更受欢迎,因为它允许在连接模型上定义属性。
让我们确保我们的 Book 和 Subject 模型具有正确的关联。假设一本书属于一个主题,而一个主题可以有多本书:
class Book < ApplicationRecord belongs_to :subject # ... validations etc. ...end
// app/models/subject.rbclass Subject < ApplicationRecord has_many :books # ... validations etc. ...endBook 模型生成器中的 subject:references 应该已经添加了 belongs_to :subject。我们需要手动向 Subject 添加 has_many :books。
实现验证 (Validations)
Section titled “实现验证 (Validations)”验证确保只有有效的数据才能保存到数据库中。它们在模型中定义。
常见的验证助手:
validates :attribute, presence: true(替代validates_presence_of)validates :attribute, uniqueness: true(替代validates_uniqueness_of)validates :attribute, numericality: true(替代validates_numericality_of)validates :attribute, length: { minimum: 5, maximum: 100 }validates :attribute, format: { with: /regex/ }validates :attribute, inclusion: { in: %w(small medium large) }validates :attribute, exclusion: { in: %w(admin root) }
让我们向 app/models/book.rb 添加一些验证:
class Book < ApplicationRecord belongs_to :subject
validates :title, presence: true, uniqueness: { scope: :subject_id, message: "should be unique for each subject" } validates :price, numericality: { greater_than_or_equal_to: 0, message: "must be a positive number or zero" }, allow_nil: true validates :description, length: { maximum: 500 }end
// app/models/subject.rbclass Subject < ApplicationRecord has_many :books validates :name, presence: true, uniqueness: trueend当您尝试保存一个 Book 或 Subject 对象(例如,book.save)时,这些验证会自动被检查。如果验证失败,save 返回 false,并且可以通过 book.errors.full_messages 访问错误信息。
查询数据 (Querying Data)
Section titled “查询数据 (Querying Data)”Active Record 提供了丰富的查询接口:
Book.all# 检索所有图书Book.find(1)# 查找 ID 为 1 的图书Book.find_by(title: 'Rails Guide')# 查找标题为 ‘Rails Guide’ 的第一本图书Book.where(subject_id: 2)# 查找所有属于主题 ID 为 2 的图书Book.where('price > ?', 50)# 价格大于 50 的图书Book.order(created_at: :desc)# 按创建日期降序排列图书Book.limit(10)# 限制结果为 10 条Book.joins(:subject).where(subjects: { name: 'Programming' })# 连接主题表并过滤
这些方法可以链式调用以构建复杂的查询。
下一步是什么?
Section titled “下一步是什么?”定义模型之后,下一步是使用 Migrations (数据库迁移) 创建或更新数据库 schema。数据库迁移允许您以一致且版本控制的方式随着时间推移演变数据库结构。