1 Active Record 是什麼?
Active Record 是 MVC 中的 M - model - 負責代表業務的系統層 資料和邏輯。 Active Record 方便業務的建立和使用 其資料需要持久儲存到資料庫的物件。它是一個 Active Record 模式的實現,它本身是對 物件關係對映系統。
1.1 Active Record 模式
Active Record 由 Martin Fowler 描述 在他的《企業應用程式架構模式》一書中。在 Active Record,物件攜帶持久資料和行為 對這些資料進行操作。 Active Record 認為確保 作為物件的一部分的資料訪問邏輯將教育使用者 關於如何寫入和讀取資料庫的物件。
1.2 物件關係對映
Object Relational Mapping,通常簡稱為ORM,是 一種將應用程式的豐富物件連線到表的技術 一個關係資料庫管理系統。使用 ORM,屬性和 應用程式中物件的關係可以很容易地儲存和 從資料庫中檢索,無需直接編寫 SQL 語句,使用較少 整體資料庫訪問程式碼。
1.3 Active Record 作為 ORM 框架
Active Record 給了我們幾個機制,最重要的是能力 到:
- 代表models 及其資料。
- 代表這些 models 之間的 associations。
- 透過相關的models 表示繼承層次。
- 在它們被持久化到資料庫之前驗證 models。
- 以面向物件的方式執行資料庫操作。
2 Active Record 中的約定優於配置
在使用其他程式語言或框架編寫應用程式時,它 可能需要寫很多配置程式碼。這是特別真實的 一般用於 ORM 框架。但是,如果您遵循 Rails,你只需要編寫很少的配置(在某些情況下不需要 配置)建立 Active Record models 時。這個想法是,如果 大多數時候你以同樣的方式配置你的應用程式然後這個 應該是預設方式。因此,需要顯式配置 僅在您無法遵循標準約定的情況下。
2.1 命名約定
預設情況下,Active Record 使用一些命名約定來找出
應建立 models 和資料庫表之間的對映。 Rails 將
將您的類名複數化以找到相應的資料庫表。因此對於
一個類 Book
,你應該有一個名為 books 的資料庫表。Rails
多元化機制非常強大,能夠多元化(和
單數化)規則詞和不規則詞。使用組成的類名時
兩個或多個單詞,model 類名應遵循 Ruby 約定,
使用CamelCase形式,而表名必須使用snake_case形式。例子:
- Model 類 - 每個單詞的第一個字母大寫的單數(例如,
BookClub
)。 - 資料庫表 - 複數用下劃線分隔單詞(例如,
book_clubs
)。
Model / 班級 | 表/架構 |
---|---|
Article |
articles |
LineItem |
line_items |
Deer |
deers |
Mouse |
mice |
Person |
people |
2.2 模式約定
Active Record 對資料庫表中的列使用命名約定, 取決於這些列的用途。
-
外部 keys - 這些欄位應按照模式命名
singularized_table_name_id
(例如,item_id
、order_id
)。這些是 當您在兩者之間建立 associations 時,Active Record 將查詢的欄位 您的 models。 -
主 keys - 預設情況下,Active Record 將使用名為的整數列
id
作為表的主 key(對於 PostgreSQL 和 MySQL,bigint
,integer
對於 SQLite)。當使用 Active Record Migrations 要建立表,將自動建立此列。
還有一些可選的列名稱將新增其他功能 到 Active Record 實例:
-
created_at
- 自動設定為當前日期和時間,當 記錄首先被建立。 -
updated_at
- 自動設定為當前日期和時間 記錄被建立或更新。 -
lock_version
- 新增 樂觀 鎖定 到 model。 -
type
- 指定 model 使用 單表 繼承。 -
(association_name)_type
- 儲存型別 多型 associations。 -
(table_name)_count
- 用於快取所屬物件的數量 associations。例如,Article
類中的comments_count
列 有很多Comment
的實例會快取現有評論的數量 對於每篇文章。
雖然這些列名是可選的,但實際上它們是由 Active Record 保留的。除非您想要額外的功能,否則請避開保留的 keywords。例如,type
是保留的 key 字,用於指定使用單表繼承 (STI) 的表。如果您沒有使用 STI,請嘗試使用類似的 key 詞,例如“上下文”,它仍然可以準確地描述您使用的 modeling 資料。
3 建立 Active Record Model
要建立 Active Record models,子類化 ApplicationRecord
類,你就可以開始了:
class Product < ApplicationRecord
end
這將建立一個 Product
model,對映到一個 products
表
資料庫。透過這樣做,您還可以對映每個
該表中的行具有 model 實例的屬性。認為
products
表是使用 SQL(或其擴充套件之一)語句建立的,例如:
CREATE TABLE products (
id int(11) NOT NULL auto_increment,
name varchar(255),
PRIMARY KEY (id)
);
上面的模式聲明瞭一個包含兩列的表:id
和 name
。每一行
該表代表了具有這兩個引數的某個產品。這樣,你
將能夠編寫如下程式碼:
p = Product.new
p.name = "Some Book"
puts p.name # "Some Book"
4 覆蓋命名約定
如果您需要遵循不同的命名約定或需要使用您的 帶有舊資料庫的 Rails 應用程式?沒問題,您可以輕鬆覆蓋 預設約定。
ApplicationRecord
繼承自 ActiveRecord::Base
,它定義了一個
一些有用的方法。您可以使用 ActiveRecord::Base.table_name=
方法來指定應該使用的表名:
class Product < ApplicationRecord
self.table_name = "my_products"
end
如果這樣做,則必須手動定義託管的類名
在您的測試中使用 set_fixture_class
方法的裝置 (my_products.yml)
定義:
class ProductTest < ActiveSupport::TestCase
set_fixture_class my_products: Product
fixtures :my_products
# ...
end
也可以覆蓋應該用作表的列
使用 ActiveRecord::Base.primary_key=
方法的主要 key:
class Product < ApplicationRecord
self.primary_key = "product_id"
end
Active Record 不支援使用名為 id
的非主要 key 列。
5 CRUD:讀寫資料
CRUD 是我們用來操作資料的四個動詞的首字母縮寫詞:Create, Read、Update 和 Delete。 Active Record 自動建立方法 允許應用程式讀取和操作儲存在其表中的資料。
5.1 建立
Active Record 物件可以從一個雜湊、一個塊中建立,或者擁有它們的
建立後手動設定屬性。 new
方法將返回一個新的
物件,而 create
將返回物件並將其儲存到資料庫中。
例如,給定一個 model User
屬性為 name
和 occupation
,
create
方法呼叫將建立一個新記錄並將其儲存到資料庫中:
user = User.create(name: "David", occupation: "Code Artist")
使用 new
方法,可以在不儲存的情況下實例化物件:
user = User.new
user.name = "David"
user.occupation = "Code Artist"
呼叫 user.save
會將記錄提交到資料庫。
最後,如果提供了一個塊,create
和 new
都會產生新的
物件到該塊進行初始化:
user = User.new do |u|
u.name = "David"
u.occupation = "Code Artist"
end
5.2 讀取
Active Record 提供了豐富的 API 來訪問資料庫中的資料。以下 是幾個由 Active Record 提供的不同資料訪問方法的例子。
# 返回一個包含所有使用者的集合
users = User.all
# 返回第一個使用者
user = User.first
# 返回第一個名為 David 的使用者
david = User.find_by(name: 'David')
# 查詢所有名為 David 的 Code Artists 使用者並按 created_at 按時間倒序排序
users = User.where(name: 'David', occupation: 'Code Artist').order(created_at: :desc)
您可以在 Active Record 中瞭解更多關於查詢 Active Record model 查詢介面 指南。
5.3 更新
一旦檢索到 Active Record 物件,就可以修改其屬性 它可以儲存到資料庫中。
user = User.find_by(name: 'David')
user.name = 'Dave'
user.save
對此的簡寫是使用雜湊對映屬性名稱到所需的 value,像這樣:
user = User.find_by(name: 'David')
user.update(name: 'Dave')
這在一次更新多個屬性時最有用。如果,另一方面
手,你想批次更新多條記錄,你可能會發現
update_all
類方法有用:
User.update_all "max_login_attempts = 3, must_change_password = 'true'"
這就像你寫的一樣:
User.update(:all, max_login_attempts: 3, must_change_password: true)
5.4 刪除
同樣,一旦檢索到一個 Active Record 物件就可以被銷燬,從而刪除 它來自資料庫。
user = User.find_by(name: 'David')
user.destroy
如果你想批次刪除多條記錄,你可以使用 destroy_by
或 destroy_all
方法:
# 查詢並刪除所有名為 David 的使用者
User.destroy_by(name: 'David')
# 刪除所有使用者
User.destroy_all
6 驗證
Active Record 允許您在寫入之前驗證 model 的狀態 進入資料庫。有幾種方法可以用來檢查你的 models 並驗證屬性 value 不為空、唯一且不 已經在資料庫中,遵循特定格式,等等。
驗證是持久化到資料庫時要考慮的一個非常重要的問題,因此
方法 save
和 update
在
執行:他們在驗證失敗時返回 false
而實際上並沒有
對資料庫執行任何操作。所有這些都有一個爆炸對應物(即
是,save!
和 update!
),它們更嚴格
如果驗證失敗,它們會引發異常 ActiveRecord::RecordInvalid
。
一個簡單的例子來說明:
class User < ApplicationRecord
validates :name, presence: true
end
irb> user = User.new
irb> user.save
=> false
irb> user.save!
ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
您可以在 Active Record 驗證 指南。
7 Callbacks
Active Record callbacks 允許您將程式碼附加到 models 的生命週期。這使您可以透過以下方式向 models 新增行為 當這些事件發生時透明地執行程式碼,比如當你建立一個新的 記錄、更新、銷燬,等等。你可以在 callbacks 中瞭解更多 Active Record Callbacks 指南。
8 Migrations
Rails 提供了一種特定領域的語言來管理稱為
遷移。 Migration 儲存在針對任何
Active Record 支援使用 rake
的資料庫。這是一個 migration
建立一個表:
class CreatePublications < ActiveRecord::Migration[7.0]
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
Rails 會跟蹤哪些檔案已提交到資料庫中,並且
提供回滾功能。要實際建立表,您需要執行 bin/rails db:migrate
,
並回滾它,bin/rails db:rollback
。
請注意,上面的程式碼與資料庫無關:它將在 MySQL 中執行, PostgreSQL、Oracle 等。您可以瞭解更多關於 migrations 的資訊 Active Record Migrations 指南。
回饋
我們鼓勵您幫助提高本指南的品質。
如果您發現任何拼寫錯誤或資訊錯誤,請提供回饋。 要開始回饋,您可以閱讀我們的 回饋 部分。
您還可能會發現不完整的內容或不是最新的內容。 請務必為 main 新增任何遺漏的文件。假設是 非穩定版指南(edge guides) 請先驗證問題是否已經在主分支上解決。 請前往 Ruby on Rails 指南寫作準則 查看寫作風格和慣例。
如果由於某種原因您發現要修復的內容但無法自行修補,請您 提出 issue。
關於 Ruby on Rails 的任何類型的討論歡迎提供任何文件至 rubyonrails-docs 討論區。