iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 11
0
自我挑戰組

rails 學習紀錄系列 第 11

[Day11] Model 關聯 (下)

關聯 - 多對多

每家店(Store)除了可以賣很多種商品之外,每種商品也可以在很多家商店販售。
多對多的關連會需要一個**第三方的資料表(Table)**來存放這兩邊 Model 的資訊(關聯表的主鍵)。


第一步建立一個專門存放 Store 跟 Product 這兩邊資訊的 Model:WareHouse
rails g model WareHouse store:references product:references
這裡的 store:references 寫法也可以換成store_id:integer 寫法,
但 references 的寫法會多做幾件事:

  1. 自動加上索引(index),加快查詢速度。
  2. 會自動在WareHouse Model 加上 belongs_to

第二步建立關聯
Store Model

class Store < ApplicationRecord
  belongs_to :user

  # 先告訴Model我们在ware_houses有很多筆資料
  has_many :ware_houses
  # 這些資料是要拿来判斷這間商店販賣多少商品
  has_many :products, through: :ware_houses
end

Product Model

class Product < ApplicationRecord
  # 先告訴Model我们在ware_houses有很多筆資料
  has_many :ware_houses
  # 這些資料是要拿来判斷這個商品在哪些商店販賣
  has_many :stores, through: :ware_houses
end

WareHouse Model

class WareHouse < ApplicationRecord
  #WareHouse要管理好商品和商店,
  #所以WareHouse會belongs_to商品和商店。
  #透過foreign_key: true 確保資料表之間的資料完整性
  belongs_to :store
  belongs_to :product
end

另一種寫法HABTM(has_and_belongs_to_many)

創建了 has_and_belongs_to_many 的關係,你就需要創建一個第三方的資料表(Table)存放雙方的資訊,只是這個資料表因為不重要也不會存取它,所以可以不需要創立Model 對應
這個第三方資料表的名字是有規定的,如果你沒有在創建關係時使用 join_table 參數,預設是「兩個資料表依照英文字母先後順序排序,中間以底線分格」,所以以我們這個例子來說,這個資料表的名字就是「products_stores」,因為字母 P 在字母 S 的前面。
(在使用 HABTM 的時候,是可以加註 join_table: "ware_houses" 的方式來指定這個資料表的名稱)

第一步建立關聯
Store Model

  class Store < ActiveRecord::Base
    has_and_belongs_to_many :products
  end

Product Model

  class Product < ActiveRecord::Base
    has_and_belongs_to_many :stores
  end

第二步新增一個 Migration 來建立資料表
rails g migration create_join_table_for_store_and_product

 class CreateJoinTableForStoreAndProduct < ActiveRecord::Migration[5.0]
    def change
      create_table :products_stores, id: false do |t|
        t.belongs_to :store, index: true
        t.belongs_to :product, index: true
      end
    end
  end
  • 記得要rails db:migration
  • 要注意上面的那個id: false ,第三方表格不代表任何 Model,所以不要給它指定主鍵,否則你可能會遇到一些莫名其妙的錯誤。

id 這是 Rails 自動幫每個資料表加的流水編號欄位,這個欄位稱為資料表的主鍵(Primary Key)。如果你不想要這個主鍵,可以在 Migration 的時候加上 id: false 參數。


該選擇 has_many ... through 還是 has_and_belongs_to_many 的寫法?

  • 當多對多關係中間的 Model 要獨立使用時,使用 has_many :through;
  • 不需要對多對多關係中間的 Model 做任何事時,保持簡單使用 has_and_belongs_to_many
    (但要記得在資料庫建立連接的資料表)。
  • 若是連接的資料表需要驗證、回呼或其他屬性時,使用 has_many :through。

參考資料:
為自己學Ruby on Rails
Rails Guide: Active Record 關聯


上一篇
[Day10] Model 關聯(上)
下一篇
[Day12]Rails RESTful
系列文
rails 學習紀錄14

尚未有邦友留言

立即登入留言