首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Ruby on Rails 開發實戰(五十七):ActiveRecord 基礎 - 多對多關聯

     編輯:Java 相關知識

多對多關聯是關係型資料庫中常見的模式。Rails 透過 has_and_belongs_to_many (HABTM) 宣告,配合中間表,讓兩個模型之間能建立雙向的集合關聯。

中間表慣例與設計

Rails 預設中間表命名為兩張關聯表名按字母序串接,以底線分隔。例如 categories 與 products 的中間表為 categories_products。中間表不包含 id 欄位,主鍵為雙外鍵複合鍵:

create table categories_products (
  category_id int not null,
  product_id  int not null,
  constraint fk_cp_category foreign key (category_id) references categories(id),
  constraint fk_cp_product  foreign key (product_id)  references products(id),
  primary key (category_id, product_id)
);

設計原因有二:

  1. 兩個外鍵的組合本身即可唯一識別關聯,無需額外代理鍵。
  2. 若中間表含 id,ActiveRecord 讀取時會將其覆蓋模型本身的 id,導致錯誤。

基本宣告與使用

class Article < ActiveRecord::Base
  has_and_belongs_to_many :users
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

宣告後,雙方皆獲得集合存取方法:

# 閱讀過文章 123 的所有用戶
article = Article.find(123)
readers = article.users

# pragdave 閱讀過的所有文章
dave = User.find_by_name("pragdave")
articles_that_dave_read = dave.articles

中間表攜帶額外屬性

若需記錄「誰在何時閱讀了哪篇文章」,可在中間表加入 read_at 欄位,並在模型中定義便利方法:

class User < ActiveRecord::Base
  has_and_belongs_to_many :articles
  
  def read_article(article)
    articles.push_with_attributes(article, :read_at => Time.now)
  end
end

push_with_attributes 會同時建立關聯並寫入中間表的額外欄位,類似於 C# 反射為物件動態賦值。

進階選項

HABTM 支援 :class_name、:foreign_key、:conditions 等常見選項,並可自訂中間表名、外鍵名、甚至 finder_sql/counter_sql/delete_sql 等完整 SQL 行為,詳細請參考 RDoc 文件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved