Разработка схемы данных рельсов для хранения снимков записей с минимальным повторением

Я построил несколько веб-приложений с использованием инфраструктуры 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

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

STI вариант 2

Как и в варианте 1, пусть RootProduct а также FrozenProduct простираться Product через STI (добавить type столбец к products Таблица). Также добавьте root_id столбец к products Таблица. RootProduct представляет состояние продукта в настоящий момент времени; FrozenProduct представляет прошлый снимок продукта в момент размещения заказа. order_products Таблица введена для хранения товаров, связанных с заказом. Перед размещением заказа каждый OrderProduct в порядке ссылки на RootProduct, После размещения заказа каждый OrderProduct ссылки на FrozenProduct созданный путем клонирования соответствующего RootProduct,

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