Избегание полиморфных ассоциаций в рельсах - PullRequest
3 голосов
/ 10 марта 2012

(извините за плохой английский)

Предположим, у меня есть модели A, B, C. У каждой модели есть один адрес.

В книге "Антипаттерны SQL: предотвращение ловушекПрограммирование базы данных "(глава 7 - Полиморфные ассоциации) Существует рецепт, позволяющий избежать таких ассоциаций с помощью" общей супер таблицы "(также называемой базовой таблицей или таблицей предков).

Полиморфно это будет:

table addresses:
    id: integer
    parent_type:string  # 'A', 'B' or 'C'
    parent_id: integer

Я знаю, что вы можете использовать таблицы пересечений, но следующее решение выглядит более отточенным:

Вместо полиморфного связывания A, B, C с Address, рецепт предлагает создать супертаблица (адресация), которая имеет только поле идентификатора (суррогатный ключ или псевдоключ).Затем другие таблицы ссылаются на адресацию.Таким образом, говорит автор, «вы можете положиться на обеспечение целостности данных вашей базы данных с помощью внешних ключей».Итак, это будет:

table addressing
    id: integer
table addresses
    id: integer
    addressing_id: integer  (foreign_key)
    zip: string
table a
    id: integer
    addressing_id: integer  (foreign_key)
    name: string
table b
    id: integer
    addressing_id: integer  (foreign_key)
    name: string
table c
    id: integer
    addressing_id: integer  (foreign_key)
    name: string

Запрос SQL будет выглядеть так:

SELECT * from a
  JOIN address USING addressing_id
  WHERE a.addressing_id = 1243 

ВОПРОС: как кодировать такой сценарий в Rails?Я пытался несколькими способами без успеха.

1 Ответ

1 голос
/ 10 марта 2012

Есть ли у объектов A, B и C один адрес? Или много адресов? Из вашего комментария ниже видно, что у каждого объекта есть один адрес.

Если у каждого объекта есть только один адрес, вы можете просто вставить внешний ключ в объекты A / B / C с идентификатором адреса. Пусть объекты Дома или Офиса имеют один адрес:

class House < ActiveRecord::Base
  belongs_to :address
end

class Office < ActiveRecord::Base
  belongs_to :address
end

Ваши таблицы office s и houses DB должны иметь внешний ключ address_id . Таким образом, вы можете получить доступ к адресу объекта с помощью чего-то вроде house.address или office.address.

Если эти объекты могут иметь много адресов, решение зависит от объектов A / B / C. Если они связаны, вы можете использовать Single Table Inheritance - Rails хорошо поддерживает этот шаблон - но без дополнительной информации трудно сказать, какой из них лучший.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...