has_and_belongs_to_many vs has_many thông qua


76

Vui lòng giải thích sự khác biệt giữa has_and_belongs_to_many và has_many thông qua mối quan hệ. Khi nào và ở đâu để sử dụng cái nào?

Câu trả lời:


108

Theo như tôi có thể nhớ, has_and_belongs_to_many cung cấp cho bạn một bảng tra cứu đơn giản tham khảo hai mô hình của bạn.

Ví dụ,

Truyện có thể thuộc nhiều thể loại. Thể loại có thể có nhiều câu chuyện.

Categories_Stories Table
story_id | category_id

has_many :through cung cấp cho bạn mô hình thứ ba có thể được sử dụng để lưu trữ nhiều phần thông tin khác không thuộc về một trong hai mô hình gốc.

Ví dụ

Người có thể đăng ký nhiều tạp chí. Tạp chí có thể có nhiều người đăng ký.

Do đó, chúng ta có thể có một mô hình đăng ký ở giữa, cung cấp cho chúng ta một bảng tương tự như ví dụ trước đó, nhưng với các thuộc tính bổ sung.

Subscriptions Table
person_id | magazine_id | subscription_type | subscription_length | subscription_date 

Và như thế.


37
lưu ý rằng bảng cần được đặt tên theo thứ tự bảng chữ cái, tức là bảng danh mục_bảng đối lập với truyện_categories - đây là quy ước làm cho nó hoạt động.
Sẽ

Cảm ơn, tôi đã thay đổi bài đăng của mình ngay bây giờ
Dan

tại sao chúng phải được xếp theo thứ tự bảng chữ cái @Will?
ctilley79

@ ctilley79 đó là quy ước được sử dụng. Vì vậy, khi hiệp hội được thiết lập, nó sẽ biết bảng nào cần tìm
Sẽ có

@ Tôi sẽ nhận được điều tương tự. Nó sẽ không đưa thuộc tính bổ sung vào cơ sở dữ liệu. Câu hỏi của tôi có câu lệnh tạo bản ghi hoạt động đang ghi vào cơ sở dữ liệu. Có thể giúp
ctilley79

39

Từ http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

Quy tắc chung đơn giản nhất là bạn nên thiết lập mối quan hệ has_many: thông qua 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 bất cứ điều gì với mô hình mối quan hệ, việc thiết lập mối quan hệ has_and_belongs_to_many có thể đơn giản hơn (mặc dù bạn cần nhớ tạo bảng tham gia trong cơ sở dữ liệu). Bạn nên sử dụng has_many: through nếu bạn cần xác thực, gọi lại hoặc các thuộc tính bổ sung trên mô hình kết hợp.


3
Tôi cũng muốn nói thêm rằng có rất nhiều phương thức rails chèn vào has_and_belongs_to_many chứ không phải has_many: through. Tất cả các phương pháp như gán một tập hợp các giá trị cho hiệp hội, dường như không hiển thị trong tài liệu hướng dẫn cho has_many: thông qua guides.rubyonrails.org/...
e3matheus

15

Quy tắc chung của tôi là, tôi có thể sử dụng danh sách các hộp kiểm ở đây không? Nếu vậy, thì đó là một hiệp hội habtm. Nếu tôi cần hộp kiểm để nắm bắt nhiều hơn về mối quan hệ chứ không chỉ đơn giản là có / không mà nó thuộc về, thì hãy sử dụng has_many: through. HABTM đơn giản như việc sử dụng phương thức _ids với một bộ sưu tập_chụp_mẫu_đơn giản. Has_many: thông qua thường liên quan đến accept_nested_attributes_for.


4

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


2

Nhiều câu trả lời làm rõ rằng bạn nên sử dụng has_and_belongs_to_manyso với has_many through:nếu bạn không cần thêm bất kỳ dữ liệu hoặc xác nhận nào trên bảng tham gia.

Tuy nhiên , hãy cẩn thận khi thực hiện cách tiếp cận này. Trong giai đoạn đầu của quá trình phát triển ứng dụng, gần như không thể biết bạn có thể cần những tính năng bổ sung hoặc xác nhận nào trong tương lai xa của vòng đời dự án của bạn. Nếu bạn đã quyết định sử dụng has_and_belongs_to_manyvà muốn thêm một điểm dữ liệu đơn giản hoặc xác thực sau 2 năm nữa, việc di chuyển thay đổi này sẽ cực kỳ khó khăn và dễ xảy ra lỗi. Để an toàn, hãy mặc định làhas_many :through


1
Bạn có thể giải thích tại sao điều này sẽ nguy hiểm và dễ xảy ra lỗi không? HABTM giống như has_many: qua, chỉ không có mô hình. Bạn có thể chuyển đổi một cách dễ dàng HABTM thành mặc dù.
grepsedawk

1
Dưới đây là một câu trả lời tốt câu hỏi của bạn, @grepsedawk: flatironschool.com/blog/...
David Hempy

2

Theo kinh nghiệm của tôi, sử dụng luôn tốt hơn has_many: throughvì bạn có thể thêm dấu thời gian vào bảng. Nhiều lần trong khi gỡ lỗi một số ActiveRecordđối tượng được kết nối thông qua HABTM, tôi nhớ da diết created_at, updated_attimestamps để có được những đầu mối những gì thực sự xảy ra. Vì vậy, hãy nhớ rằng nó có thể giúp bạn gỡ lỗi, điều tra các vấn đề với các mối quan hệ dữ liệu trong bối cảnh thời gian, bởi vì nếu không có nó, bạn sẽ bị "mù" khi quan hệ được tạo hoặc cập nhật.

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.