Khi nào nên sử dụng một has has has has: thông qua mối quan hệ của Rails trong Rails?


123

Tôi đang cố gắng để hiểu những gì has_many :throughvà khi nào sử dụng nó (và làm thế nào). Tuy nhiên, tôi không nhận được nó. Tôi đang đọc Beginning Rails 3 và tôi đã thử Googling, nhưng tôi không thể hiểu được.

Câu trả lời:


177

Nói rằng bạn có hai mô hình: UserGroup.

Nếu bạn muốn có người dùng thuộc các nhóm, thì bạn có thể làm một cái gì đó như thế này:

class Group < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :group
end

Điều gì nếu bạn muốn theo dõi siêu dữ liệu bổ sung xung quanh hiệp hội? Ví dụ: khi người dùng tham gia nhóm, hoặc có lẽ vai trò của người dùng trong nhóm là gì?

Đây là nơi bạn làm cho hiệp hội trở thành một đối tượng hạng nhất:

class GroupMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :group

  # has attributes for date_joined and role
end

Điều này giới thiệu một bảng mới và loại bỏ group_idcột khỏi bảng của người dùng.

Vấn đề với mã này là bạn phải cập nhật mọi nơi bạn sử dụng lớp người dùng và thay đổi nó:

user.groups.first.name

# becomes

user.group_memberships.first.group.name

Loại mã này hút, và nó làm cho việc giới thiệu những thay đổi như thế này đau đớn.

has_many :through cung cấp cho bạn tốt nhất của cả hai thế giới:

class User < ActiveRecord::Base
  has_many :groups, :through => :group_memberships  # Edit :needs to be plural same as the has_many relationship   
  has_many :group_memberships
end

Bây giờ bạn có thể coi nó như một bình thường has_many, nhưng có được lợi ích của mô hình kết hợp khi bạn cần.

Lưu ý rằng bạn cũng có thể làm điều này với has_one.

Chỉnh sửa: Giúp dễ dàng thêm người dùng vào nhóm

def add_group(group, role = "member")
  self.group_associations.build(:group => group, :role => role)
end

2
Đây là nơi tôi muốn thêm một phương thức trên usermô hình để thêm nhóm. Một cái gì đó giống như chỉnh sửa tôi vừa thực hiện. Hi vọng điêu nay co ich.
Ben Scheirman

Tôi hiểu rồi, tôi cũng phải viết user.groups << groupà? Hoặc là tất cả mọi thứ được xử lý bởi hiệp hội này?
LuckyLuke

Tôi có một lớp giống như nhóm_membership và tôi đang gặp vấn đề khi sử dụng cô gái nhà máy với nó, bạn có thể giúp tôi không?
Ayman Salah

Tôi sẽ sử dụng "has_many: group_memberships". Sử dụng số ít sẽ hoạt động, nhưng user.group_membership sẽ một bộ sưu tập và user.group_memberships sẽ không hoạt động.
calasyr

Đó là một lỗi đánh máy. Đã sửa.
Ben Scheirman

212

Giả sử bạn có những mô hình này:

Car
Engine
Piston

Một chiếc xe has_one :engine
Một động cơ belongs_to :car
Một động cơ has_many :pistons
Pistonbelongs_to :engine

Một chiếc xe hơi has_many :pistons, through: :engine
Pistonhas_one :car, through: :engine

Về cơ bản, bạn đang ủy thác một mối quan hệ mô hình cho một mô hình khác, vì vậy thay vì phải gọi car.engine.pistons, bạn chỉ có thể làmcar.pistons


9
Điều này là làm cho rất nhiều ý nghĩa!
RajG

24
Tôi gọi đây là SACA - ShortAndClearAnswer.
Asme chỉ cần

18

ActiveRecord Tham gia bàn

has_many :throughvà các has_and_belongs_to_manymối quan hệ hoạt động thông qua một bảng tham gia , là một bảng trung gian thể hiện mối quan hệ giữa các bảng khác. Không giống như truy vấn THAM GIA, dữ liệu thực sự được lưu trữ trong một bảng.

Sự khác biệt thực tế

Với has_and_belongs_to_many, bạn không cần khóa chính và bạn truy cập vào các bản ghi thông qua quan hệ ActiveRecord thay vì thông qua mô hình ActiveRecord. Bạn thường sử dụng HABTM khi bạn muốn liên kết hai mô hình với mối quan hệ nhiều-nhiều.

Bạn sử dụng has_many :throughmối quan hệ khi bạn muốn tương tác với bảng tham gia dưới dạng mô hình Rails, hoàn thành với các khóa chính và khả năng thêm các cột tùy chỉnh vào dữ liệu đã tham gia. Cái sau đặc biệt quan trọng đối với dữ liệu có liên quan đến các hàng được nối, nhưng không thực sự thuộc về các mô hình liên quan - ví dụ: lưu trữ một giá trị được tính toán xuất phát từ các trường trong hàng được nối.

Xem thêm

Trong Hướng dẫn về Hiệp hội hồ sơ hoạt động , khuyến nghị có nội dung:

Nguyên tắc đơn giản nhất là bạn nên thiết lập has_many: thông qua mối quan hệ nếu bạn cần làm việc với mô hình mối quan hệ như một thực thể độc lập. Nếu bạn không cần làm gì với mô hình mối quan hệ, có thể đơn giản hơn để thiết lập mối quan hệ has_and_belongs_to_many (mặc dù bạn sẽ cần nhớ để tạo bảng tham gia trong cơ sở dữ liệu).

Bạn nên sử dụng has_many: thông qua nếu bạn cần xác thực, gọi lại hoặc thuộc tính bổ sung trên mô hình tham gia.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.