rails3 и правильный способ использования ассоциаций
Я делаю свое первое приложение rails(3).
Ассоциации не имеют смысла. Во-первых, даже направляющие не объясняют, что они делают, они просто объясняют, как их использовать. Из того, что я понимаю, ассоциации делают две вещи:
a) Allow ActiveRecord to optimize the structure of the database.
b) Allow ActiveRecord to offer an alternate ruby syntax for
joins and the like (SQL queries). I want this.
Я пытаюсь понять ассоциации и как правильно их использовать. На основании приведенного ниже примера кажется, что ассоциации "нарушены" или, по крайней мере, документация такова.
Рассмотрим тривиальную версию моего приложения. Учитель, изменяющий словарные списки для изучения.
Есть 3 соответствующие таблицы для этого обсуждения. Для ясности я просто включил в таблицу определение инструмента annotate(1) и удалил ненужные поля / столбцы.
Таблица управления списками слов:
Table name: wordlist_mgmnt_records
id :integer not null, primary key
byline_id :integer(8) not null
Таблица, которая отображает слова в список слов:
Table name: wordlists
wordlist_mgmnt_id :integer not null
word_id :integer not null
Мы на самом деле не заботимся о самих словах. Но мы заботимся о последней таблице, подписи:
Table name: bylines
id :integer(8) not null, primary key
teacher_id :integer not null
comment :text not null
Bylines записывают, кто, какой инструмент использовался, где, когда и т. Д. Bylines в основном используются для устранения неполадок, что случилось, чтобы я мог объяснить пользователям, что они должны были сделать (и / или исправить свои ошибки).
Преподаватель может изменять одну или несколько записей управления списком слов за раз (так называемый однострочный). Иными словами, одно изменение может обновить несколько списков слов.
Для wordlist_mgmnt_records ассоциации будут:
has_many :bylines # the same byline id can exist
# in many wordlist_mgmnt_records
Но какова соответствующая запись для bylines?
Книга Beginning Rails 3 (Carneiro, et al) гласит:
"Note: For has_one and has_many associations, adding a belongs_to
on the other side of the association is always recommended. The
rule of thumb is that the belongs_to declaration always goes in
the class with the foreign key."
[Да, я также посмотрел онлайн руководство по рельсам для этого. Не помогло ]
Для таблицы / класса bylines я действительно хочу сказать?
belongs_to :wordlist_mgmnt_records
Это действительно не имеет смысла. таблица bylines в основном принадлежит каждой таблице в базе данных с bylines_id. Так я бы действительно сказал, что принадлежит всем им? Разве это не установило бы внешние ключи во всех других таблицах? Это, в свою очередь, сделает изменения дороже (слишком много циклов ЦП), чем я действительно хочу. Некоторые изменения затронули множество таблиц, некоторые из них очень большие. Я ценю скорость при обычном использовании и готов подождать, чтобы найти заголовки без внешних ключей при использовании заголовков для очистки / ремонта.
Что приносит нам полный круг. Что на самом деле делают ассоциации в рельсах, и как их разумно использовать?
Просто использование ассоциаций, потому что вы не можете быть правильным ответом, но как иначе вы получаете добавленный синтаксис соединения?
1 ответ
Я постараюсь помочь вашему замешательству....
Byline может иметь несколько wordlist_mgmnt_records
так определяя has_many
там, кажется, имеет смысл.
Я не уверен, что понимаю вашу путаницу в другом направлении. Поскольку вы определили атрибут wordlist_mgmnt_records.byline_id
любая wordlist_mgmnt_record
может "иметь" (принадлежать) только одну подпись. Вы просто определяете гусиную лапку через ruby (если вам нравятся диаграммы базы данных):
wordlist_msgmnt_records (many)>>----------(one) byline
Или прочитайте по-английски: "В одном подписи может быть много слов wordlist_mgmnts, а многие отдельные слова в wordlist_mgmnt могут принадлежать одному заголовку"
Добавление определения own_to в модель wordlist_mgmnt не влияет на производительность запросов, просто позволяет вам делать такие вещи, как:
@record = WordlistMgmntRecord.find(8)
@record_byline = @record.byline
Кроме того, вы можете делать соединения на таких столах, как:
@records = WordlistMgmntRecord.joins(:byline).where({:byline => {:teacher_id => current_user.id}})
Который будет выполнять этот SQL:
SELECT wordlist_mgmnt_records.*
FROM wordlist_mgmnt_records
INNER JOIN bylines
ON wordlist_mgmnt_records.byline_id = bylines.id
WHERE bylines.teacher_id = 25
(Предполагается, что current_user.id
вернул 25)
Это основано на вашем текущем дизайне БД. Если вы обнаружите, что есть способ реализовать желаемую функциональность без byline_id
в качестве внешнего ключа в wordlist_mgmnt_records
стол, то вы бы изменить ваши модели, чтобы приспособить его. Однако, похоже, именно так должна выглядеть нормализованная база данных, и я не совсем уверен, каким другим способом вы бы это сделали.