Разработка схемы данных рельсов для хранения снимков записей с минимальным повторением
Я построил несколько веб-приложений с использованием инфраструктуры Ruby on Rails и заметил общую проблему проектирования: из-за переменной природы некоторых данных мне часто нужно хранить копию записи с событием, которое происходит в определенное время.
Например, рассмотрим приложение магазина с products
а также orders
столы. Когда пользователь помещает Order
приложение должно хранить копии Product
записи в заказе, чтобы сохранить состояние этих продуктов во время заказа. Таким образом, будущие модификации Product
не влияют на прошлые заказы.
Я обычно решал эту проблему, вводя другую таблицу, скажем order_products
, для хранения товаров, связанных с заказом. каждый OrderProduct
затем belongs_to
база Product
, но все еще хранит копии атрибутов Product
; Я написал обратные вызовы save, чтобы синхронизировать атрибуты двух записей до тех пор, пока пользователь не разместит порядок, не связывая записи.
Проблема с этим дизайном является дублирование полей данных между products
а также order_products
столы; всякий раз, когда я изменяю Product
атрибуты, я должен помнить, чтобы изменить OrderProduct
атрибуты таким же образом и обновить обратные вызовы сохранения. Более того, если Product
имеет ассоциации, которые должны быть скопированы в соответствующий OrderProduct
Повторение в таблицах становится громоздким.
Как я могу построить схему для хранения этих "снимков" продукта, связанных с заказами без или с минимальным повторением?
(Обратите внимание, что я предоставил бетон products
а также orders
таблицы для ясности, но я столкнулся с одной и той же абстрактной проблемой в нескольких различных сценариях.)
РЕДАКТИРОВАТЬ: Вот аналогичный вопрос, автор которого предлагает использовать таблицы истории для хранения снимков: структура базы данных для хранения исторических данных. Принятый ответ предлагает решение, которое я представил выше.
1 ответ
Вот два варианта, которые, по-видимому, сводят к минимуму повторение схемы в этом сценарии. Оба решения основаны на наследовании одной таблицы (STI).
Опция 1
Позволять RootProduct
а также OrderProduct
простираться Product
через STI (добавить type
столбец к products
Таблица). Также добавьте order_id
а также root_id
столбцы к products
Таблица. RootProduct
представляет отдельный продукт (не связанный с заказом, order_id = null
а также root_id = null
). OrderProduct
напротив, связан с заказом, а также RootProduct
из которого он был создан. Когда пользователь добавляет RootProduct
клонировать продукт как OrderProduct
и сохранить ссылку на корневой продукт в root_id
, Пока заказ остается неразмещенным, синхронизируйте атрибуты двух записей продукта, но отделяйте записи после того, как пользователь разместит заказ. OrderProduct
записи служат в качестве снимков продукта.
Вариант 2
Как и в варианте 1, пусть RootProduct
а также FrozenProduct
простираться Product
через STI (добавить type
столбец к products
Таблица). Также добавьте root_id
столбец к products
Таблица. RootProduct
представляет состояние продукта в настоящий момент времени; FrozenProduct
представляет прошлый снимок продукта в момент размещения заказа. order_products
Таблица введена для хранения товаров, связанных с заказом. Перед размещением заказа каждый OrderProduct
в порядке ссылки на RootProduct
, После размещения заказа каждый OrderProduct
ссылки на FrozenProduct
созданный путем клонирования соответствующего RootProduct
,