重学rails: active-record 基础
基本的 active-record 使用
What
Active Record 是MVC中 M 的一部分- 模型 - 是系统中负责表示数据和业务逻辑的层。Active Record 可帮助您创建和使用 Ruby 对象,其属性需要持久存储到数据库中。
命名约定
对于由两个或多个单词组成的类名,模型类名将遵循使用 UpperCamelCase 名称的 Ruby 约定。在这种情况下,数据库表名称将采用 snake_case 名称。例如:
BookClub
是模型类,单数,每个单词的首字母大写。book_clubs
是匹配的数据库表,复数形式,用下划线分隔单词。
以下是一些模型类名和对应表名的示例:
型号/类别 | 表/模式 |
---|---|
|
|
|
|
|
|
|
|
架构约定
Active Record 也使用数据库表中列名的约定,具体取决于这些列的用途。
- 主键- 默认情况下,Active Record 将使用一个整数列
id
作为表的主键(bigint
对于 PostgreSQL、MySQL 和 MariaDB,integer
对于 SQLite)。使用Active Record Migrations创建表时,将自动创建此列。 - 外键- 这些字段应按照以下模式命名
singularized_table_name_id
(例如order_id
,line_item_id
)。当您在模型之间创建关联时,Active Record 将查找这些字段。
还有一些可选的列名将为 Active Record 实例添加附加功能:
created_at
- 首次创建记录时自动设置为当前日期和时间。updated_at
- 每当创建或更新记录时自动设置为当前日期和时间。lock_version
-向模型添加乐观锁定。type
- 指定模型使用单表继承。(association_name)_type
— 存储多态关联的类型。(table_name)_count
- 用于缓存关联上的所属对象的数量。例如,如果Article
s 有很多Comment
s, 表comments_count
中的一列articles
将缓存每篇文章的现有评论数量。
创建Modal 对应SQL
class Book < ApplicationRecord
end
CREATE TABLE books (
id int(11) NOT NULL auto_increment,
title varchar(255),
author varchar(255),
PRIMARY KEY (id)
);
创建 Migrations
bin/rails generate migration CreateBooks title:string author:string
# Note:
# The `id` column, as the primary key, is automatically created by convention.
# Columns `created_at` and `updated_at` are added by `t.timestamps`.
class CreateBooks < ActiveRecord::Migration[8.0]
def change
create_table :books do |t|
t.string :title
t.string :author
t.timestamps
end
end
end
创建命名空间模型
bin/rails generate model Book::Order
module Book
def self.table_name_prefix
"book_"
end
end
class Book::Order < ApplicationRecord
end
# 查看表名
Book::Order.table_name
# => "book_orders"
自定义 table_name
class Book < ApplicationRecord
self.table_name = "my_books"
end
自定义 primary_key
class Book < ApplicationRecord
self.primary_key = "book_id"
end
CURD 之 Create
创建,并存数据库,已经产生ID
book = Book.create(title: "The Lord of the Rings", author: "J.R.R. Tolkien")
# Note that the `id` is assigned as this record is committed to the database.
book.inspect
# => "#<Book id: 106, title: \"The Lord of the Rings\", author: \"J.R.R. Tolkien\", created_at: \"2024-03-04 19:15:58.033967000 +0000\", updated_at: \"2024-03-04 19:15:58.033967000 +0000\">"
CURD 之 New
创建,但不存数据库,还没有产生 ID
book = Book.new
book.title = "The Hobbit"
book.author = "J.R.R. Tolkien"
# Note that the `id` is not set for this object.
book.inspect
# => "#<Book id: nil, title: \"The Hobbit\", author: \"J.R.R. Tolkien\", created_at: nil, updated_at: nil>"
# The above `book` is not yet saved to the database.
book.save
book.id # => 107
# Now the `book` record is committed to the database and has an `id`.
/* Note that `created_at` and `updated_at` are automatically set. */
INSERT INTO "books" ("title", "author", "created_at", "updated_at") VALUES (?, ?, ?, ?) RETURNING "id" [["title", "Metaprogramming Ruby 2"], ["author", "Paolo Perrotta"], ["created_at", "2024-02-22 20:01:18.469952"], ["updated_at", "2024-02-22 20:01:18.469952"]]
查询 R
- all: 所有
- find/find_by: 查询单个
- where: 查询多个
# Return a collection with all books.
books = Book.all
# Return a single book.
first_book = Book.first
last_book = Book.last
book = Book.take
# Returns the first book with a given title or `nil` if no book is found.
book = Book.find_by(title: "Metaprogramming Ruby 2")
# Alternative to Book.find_by(id: 42). Will throw an exception if no matching book is found.
book = Book.find(42)
# Find all books by a given author, sort by created_at in reverse chronological order.
Book.where(author: "Douglas Adams").order(created_at: :desc)
更新 Update
- 标准写法
- 简化写法
- 一次性更新所有的值
book = Book.find_by(title: "The Lord of the Rings")
book.title = "The Lord of the Rings: The Fellowship of the Ring"
book.save
book = Book.find_by(title: "The Lord of the Rings")
book.update(title: "The Lord of the Rings: The Fellowship of the Ring")
Book.update_all(status: "already own")
删除 Destroy
book = Book.find_by(title: "The Lord of the Rings")
book.destroy
# Find and delete all books by Douglas Adams.
Book.destroy_by(author: "Douglas Adams")
# Delete all books.
Book.destroy_all
验证 Validation
- 验证存在
- 错误信息
class User < ApplicationRecord
validates :name, presence: true
end
user = User.create
user.errors.full_messages
回调 Callback(Event)
class User < ApplicationRecord
after_create :log_new_user
private
def log_new_user
puts "A new user was registered"
end
end
@user = User.create
# A new user was registered
Relation
- 1 对多
class Author < ApplicationRecord
has_many :books
end