has_and_belongs_to_many vs has_many through


76

Поясніть, будь ласка, різницю між has_and_belongs_to_many та has_many через відносини. Коли і де використовувати який?

Відповіді:


108

Наскільки я пам’ятаю, has_and_belongs_to_manyви отримуєте просту таблицю пошуку, яка посилається на ваші дві моделі.

Наприклад,

Історії можуть належати до багатьох категорій. Категорії можуть мати багато історій.

Categories_Stories Table
story_id | category_id

has_many :through дає вам третю модель, яка може бути використана для зберігання іншої інформації, яка не належить до жодної з оригінальних моделей.

Наприклад

Людина може передплатити багато журналів. Журнали можуть мати багато передплатників.

Таким чином, ми можемо мати модель підписки посередині, яка дає нам подібну таблицю до попереднього прикладу, але з додатковими властивостями.

Subscriptions Table
person_id | magazine_id | subscription_type | subscription_length | subscription_date 

І так далі.


37
Зверніть увагу, що таблиця повинна бути названа в алфавітному порядку, тобто таблиця category_stories на відміну від stories_categories - саме така умова робить її роботою.
Буде

Дякую, я змінив свою посаду зараз
Ден,

чому вони повинні бути в алфавітному порядку @Will?
ctilley79

@ ctilley79, що є конвенцією, що використовується. Отже, коли асоціація створена, вона знає, на який стіл слід звертати увагу
Вілл

@Чи отримаю я саме те саме. Він не буде включати додатковий атрибут у письмовій формі до бази даних. У моєму запитанні є оператор create, який активний запис записує в базу даних. Це може допомогти
ctilley79

39

З http://guides.rubyonrails.org/association_basics.html#choose-between-has-many-through-and-has-and-belongs-to-many

Найпростішим емпіричним правилом є те, що вам слід встановити has_many: through relationship, якщо вам потрібно працювати з моделлю відносин як незалежною сутністю. Якщо вам не потрібно нічого робити з моделлю взаємозв'язку, можливо, буде простіше встановити зв'язок has_and_belongs_to_many (хоча вам потрібно пам'ятати про створення таблиці об'єднання в базі даних). Ви повинні використовувати has_many: через, якщо вам потрібні перевірки, зворотні виклики або додаткові атрибути на моделі об'єднання.


3
Я б також додав, що існує безліч методів, що вставляють рейки до has_and_belongs_to_many, а не до has_many: through. Всі методи, такі як присвоєння колекції значень асоціації, схоже, не відображаються в документації для has_many: через guides.rubyonrails.org/…
e3matheus

15

Моє емпіричне правило полягає в тому, чи можу я обійтися списком прапорців тут? Якщо так, то це асоціація хабтм. Якщо мені потрібен прапорець, щоб охопити більше про стосунки, ніж просто так / ні, вони належать, тоді використовуйте has_many: through. HABTM так само простий, як використання методу _ids із простою_формацією collection_check_boxes. Has_many: через часто включає accept_nested_attributes_for.


4

Ви повинні використовувати has_many: через, якщо вам потрібні перевірки, зворотні виклики або додаткові атрибути на моделі об'єднання.


2

Багато відповідей пояснюють, що вам слід використовувати has_and_belongs_to_manyпроти, has_many through:якщо вам не знадобляться додаткові дані або перевірки в таблиці приєднання.

Однак остерігайтеся приймати такий підхід. На ранніх стадіях розробки додатків майже неможливо знати, які додаткові функції або перевірки можуть вам знадобитися в подальшому майбутньому життєвому циклі вашого проекту. Якщо ви вирішили використовувати has_and_belongs_to_manyі хочете додати одну просту точку даних або перевірку через 2 роки, перенесення цієї зміни буде надзвичайно складним та схильним до помилок. Щоб бути в безпеці, за замовчуваннямhas_many :through


1
Чи можете ви пояснити, чому це може бути небезпечним та схильним до помилок? HABTM - те саме , що has_many: наскрізь, лише без моделі. Ви можете дуже витончено перетворити HABTM на все-таки.
grepsedawk

1
Ось хороший відповідь на ваше запитання, @grepsedawk: flatironschool.com/blog / ...
Девід конопляний

2

З мого досвіду, його завжди краще використовувати, has_many: throughоскільки ви можете додавати позначки часу до таблиці. Багато разів під час налагодження деяких ActiveRecordоб'єктів, підключених через HABTM, я відсутній created_at, updated_atмітки часу, щоб зрозуміти, що насправді сталося. Тож майте на увазі, що це може допомогти вам налагоджувати, досліджувати проблеми з відносинами даних у контексті часу, тому що без нього ви «сліпі», коли відносини створювались або оновлювались.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.