2013-09-20 2 views
0

Скажем, у меня есть приложение Rails 3 со следующими модельными ассоциациями:Плохой дизайн данных для дублирования ассоциаций Rails?

user 
    belongs_to :group 

item 
    belongs_to :group 
    belongs_to :user 

Если код не обязательно написано, это может привести к неточностям данных, где:

item.group

и

item.user.group

больше не возвращают ту же группу, когда они должны. Элемент всегда должен принадлежать только одной группе.

Мое понимание заключается в том, что эта дублируемая ассоциация, возможно, была создана для упрощения запросов (уменьшите количество подключенных таблиц).

Итак, мой вопрос в том, является ли это просто ужасной практикой или это вопрос правильных компромиссов, что существуют случаи, когда дублирование данных и ассоциации приемлемо, потому что мы можем упростить запрос с меньшим количеством объединений.

UPDATE

До сих пор кажется, что ответ «компромиссы», а не «плохая практика/код запах».

Там, кажется, несколько способов, которыми это может быть обработан, вероятно, с сочетанием ограничений, преимущества, недостатки, прецедентами и т.д.:

1) Денормализованные, дублированные данные, как выше 2) пункт has_one: группа ,: через =>: пользователь 3) элемент делегат: группа: to =>: пользователь

Я пытаюсь понять различия между подходами № 2 и № 3. После экспериментов с обоими подходами в консоли кажется, что запросы, созданные Rails при вызове item.group, будут разными. (2) создает один запрос, который объединяет группы и пользователей. (2) создает два запроса, сначала для поиска пользователя, а затем для поиска группы на основе пользователя.

+0

@BillyChan Почему вопрос не имеет недопустимого кода или даже никакого кода вообще? Концепции можно обсуждать без кода. Можно задать вопросы о концепциях. – Ben

+0

Бен, извините, если мои слова звучат не вежливо. Но ваш вопрос выглядит не так серьезно. Если элемент принадлежит пользователю, по крайней мере у пользователя должно быть много элементов? Почему вы не можете написать это под вопросом? Или это отсутствие другой стороны также является частью краевого случая? Почему вы не можете показать полную групповую ассоциацию?Край случае не ошибается, но было бы лучше, чтобы все остальные части были чистыми и статичными. –

+0

Билли, я решил добавить наименьшее количество псевдокодов, что было необходимо для понимания вопроса. Я сделал это, потому что он делает меньше чтения для других пользователей stackoverflow. Я не думал, что другие ассоциации актуальны. Если пользователь has_many items или has_one не имеет значения для вопроса. Вопрос напрямую связан с тем, не имеет ли дублирующихся данных или, следовательно, вероятность потери целостности данных, является оправданным компромиссом, если вы получаете производительность запросов и более простые запросы. – Ben

ответ

1

Я думаю, что это вопрос правильных компромиссов. Строго говоря, в полностью нормализованной базе данных ваша таблица элементов не будет иметь столбец группы, вместо этого она всегда будет проходить через таблицу users, чтобы найти группу. Это наименьшее количество дублирования и, таким образом, самая высокая целостность данных, но за счет того, что вы делаете это дополнительное соединение каждый раз, когда хотите найти группу элементов. Я предполагаю, что пользователь также принадлежит только одной группе. Если пользователь может принадлежать многим группам, то я думаю, вам нужно будет иметь этот столбец items.group_id, чтобы узнать, к какой из этих групп принадлежит элемент.

Если вы хотите получить более быструю производительность запроса при поиске, вы можете сохранить дополнительную ассоциацию, как и у вас, и добавить дополнительный крючок before_ *, чтобы убедиться, что item.group_id = item.user.group_id и повысить ошибку проверки если они не совпадают. Это сделало бы проверку/вставку немного медленнее, но обеспечит максимальную целостность данных и позволит вам получить немного лучшую производительность при чтении из базы данных.

+0

Спасибо, это именно тот комментарий, который я ищу. И да, в этом примере пользователь может принадлежать только одной группе. – Ben

+0

Обратите внимание, что шаблон 'has_many: through' часто применяется в этом случае (если вы решите не денормализовать данные) - если пользователь' принадлежит_группе' и элементу 'принадлежит_то' пользователю, вы также можете сказать, что элемент' has_one: group ,: через =>: пользователь'. Затем вы можете вызвать «.группу» на элементе и получить группу связанного с ней пользователя. – MrTheWalrus

+0

@MrTheWalrus: спасибо, что вызывает некоторые дополнительные проблемы для меня, редактируя исходный вопрос. – Ben

Смежные вопросы