Избегание полиморфных ассоциаций в рельсах

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

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

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

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

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

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

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

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 ответ

Решение

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

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

class House < ActiveRecord::Base
  belongs_to :address
end

class Office < ActiveRecord::Base
  belongs_to :address
end

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

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

Другие вопросы по тегам