跳轉到內容

Ruby on Rails/ActiveRecord/Associations

來自華夏公益教科書

關聯是連線兩個模型的方法。物件操作變得非常簡單。關聯描述了模型之間關係的作用。ActiveRecord 關聯可以用來描述模型之間的一對一 (1:1)、一對多 (1:n) 和多對多 (n:m) 關係。有幾種型別的關聯

  • belongs_to
  • has_one 形成一對一關係
  • has_one :through 是一種建立一對一關係的不同方法


  • has_many
  • belongs_to 形成一對多關係


  • has_and_belongs_to_many 或另一種方法
  • has_many :through 建立多對多關係

對於所有以下示例,我們假設以下 4 個模型

class Product < ActiveRecord::Base
end

class Category < ActiveRecord::Base
end

class Rating < ActiveRecord::Base
end

class Tag < ActiveRecord::Base
end

也檢視以下模型的 ER 圖

belongs_to

[編輯 | 編輯原始碼]

belongs_to關聯建立與其他模型的一對一 (1:1) 或一對多 (1:n) 關係。

在我們的示例中,一個 Rating 屬於一個 Product,因此我們需要設定一個belongs_to關聯。

class Product < ActiveRecord::Base
  belongs_to :rating
end

產品儲存 Rating 的 ID,它們之間有一對一關係。這意味著:一個產品屬於一個類別,一個產品屬於一個 Rating。

has_one關聯也是一對一關係。它宣告 Product 模型中的每個產品例項都只有一個 rating_id。

class Rating< ActiveRecord::Base
  has_one :product
end

由於 Rating 和 Product 之間存在一對一關係,因此我們可以選擇將引用放在哪裡。因為我們將引用 (rating_id) 放入 Product (檢視 Product 模型中的 belongs_to :rating),因此 Rating 的關聯必須是 has_one:product。Has_onebelongs_to始終一起形成關係。

這是與其他模型的一對多連線。在這種情況下,一個類別有多個產品。注意拼寫,如果您使用has_many。您要引用的模型需要用複數形式。

class Category< ActiveRecord::Base
  has_many :products #note the plural here!
end

class Product< ActiveRecord::Base
  belongs_to :category
end

類別和產品形成一對多關係。由於一個類別有多個產品,因此我們將has_many關聯放在類別中。注意產品還需要包含對類別的引用。一個產品只屬於一個類別,因此我們將belongs_to :category放在 Product 模型中。

has_and_belongs_to_many

[編輯 | 編輯原始碼]

也稱為:HABTM

Has_and_belongs_to_many是最複雜的關聯。您需要牢記一些事項:由於關係型資料庫的工作方式,您無法設定直接關係。您需要建立連線表。這可以透過遷移輕鬆完成。如果我們想為產品和標籤建立 HABTM 關聯,則連線表的關聯可能如下所示

class CreateProductTagJoinTable < ActiveRecord::Migration
  def self.up
   create_table :products_tags, :id => false do |t| #we DO NOT need the id here!
     t.integer :product_id #alternatively, we can write t.references :product
     t.integer :tag_id
   end
  end

  def self.down
    drop_table :products_tags
  end
end

因為我們不需要在連線表中使用主鍵,所以我們使用:id => false來阻止自動建立主鍵列。表名必須按字母順序排列。字母 "P" 在 "T" 之前,因此表名必須是 products_tags(注意:複數)。

class Product< ActiveRecord::Base
  has_and_belongs_to_many :tags
end

class Tag< ActiveRecord::Base
   has_and_belongs_to_many :products
end

has_many :through

[編輯 | 編輯原始碼]

此關聯是形成多對多關係的另一種方法。請考慮以下 ER 圖來顯示關係。

class Product < ActiveRecord::Base
  belongs_to :category
  belongs_to :supplier
end

class Supplier < ActiveRecord::Base
  has_many :products
  has_many :categories, :through => :products
end

class Category< ActiveRecord::Base
  has_many :products
  has_many :suppliers, :through => :products
end

我們不使用連線表,而是使用另一個模型來建立關係。如果我們想找出哪個供應商負責某個特定類別,我們需要使用產品將模型連線在一起。這樣,我們就可以在充當連線模型的真實模型中儲存更多資料。每當您需要儲存也屬於關聯的額外資料(例如建立日期)時,您可能希望使用這種型別的關聯。

has_one :through

[編輯 | 編輯原始碼]

has_many :through, has_one :through關聯使用一個“額外”模型來形成關係。

請考慮這種視覺關係

class Network < ActiveRecord::Base
  has_one :group
  has_one :user, :through =>:group
end

class Group < ActiveRecord::Base
  belongs_to :network
  has_one :user
end

class User< ActiveRecord::Base
  belongs_to :group
end

注意:此示例假設組內的成員資格對每個使用者都是排他的。

華夏公益教科書