#ruby-on-rails
#ruby-on-rails
Вопрос:
Я планирую свою базу данных прямо сейчас. И в процессе объединения моего ERD я быстро заметил, что все таблицы связаны КАК с моей shops
таблицей, так и с моей amazon_credentials
таблицей. Есть ли лучший / более эффективный дизайн или взаимосвязь, которые я могу внедрить, чтобы сделать мою базу данных более эффективной и простой в использовании?
Вот ссылка на мой текущий ERD в Whimsical
Еще одно предостережение: я не хочу проходить через свою amazon_credentials
таблицу для всех запросов. Например.. Я хотел бы иметь возможность делать и то Shop.find(1).packing_slips
, и другое, и получать все packing_slips
для a shop
, а также иметь возможность делать это Shop.find(1).amazon_credentials.packing_slips
, чтобы получить packing_slips
для определенного рынка.
Размышляя об этом, я почти использую свою amazon_credentials
таблицу в качестве дублера, marketplace
поскольку учетные данные по своей сути ограничены marketplace
Это хороший дизайн или есть лучший способ?
Комментарии:
1. У вас есть это, чтобы магазин мог использовать 0 или более учетных данных Amazon. Это то, что вы хотите?
2. Вы используете Rails? » Я не хочу проходить через мою таблицу amazon_credentials для всех запросов » Почему бы и нет?
3. @Schwern привет .. да, используя Rails.. и да
shop
, может быть 0 или большеamazon_credentials
4. Если у магазина может быть много AmazonCredentials, как вы узнаете, какой использовать?
5. @Schwern это основано на адресе клиентов в
order
. themarketplace
в пределахamazon_credentials
конкретных стран. и на основе адреса клиента используется правильный набор учетных данных..
Ответ №1:
Дублированные связи с магазинами и AmazonCredentials, разбросанные по базе данных, можно заменить косвенными связями. К счастью, Rails предоставляет методы, позволяющие сделать косвенные отношения прямыми: has_many :through .
И вам не нужно доводить ее до совершенства с первого раза или прогнозировать все возможные варианты использования. Миграции помогают безопасно изменять дизайн в соответствии с меняющимися требованиями.
Давайте построим основные взаимосвязи. Я сделал некоторые предположения, например, методы доставки привязаны к торговой площадке.
- Продукт содержит информацию о себе.
- В магазине есть продукты, способы их продажи (торговая площадка), учетные данные для этих торговых площадок и заказы.
- В заказе указывается, кто сделал заказ, из какого магазина, через какую торговую площадку, какие продукты были заказаны и сколько по какой цене, как они отправляются и как их отслеживать.
- На торговой площадке есть методы доставки.
Сразу же мы сталкиваемся с проблемой: учетные данные. Магазину нужны учетные данные для каждой торговой площадки. Это решается с помощью промежуточной модели: MarketplaceAccount, которая объединяет магазин и маркетплейс с учетными данными магазина. Учетные данные могут быть преобразованы в строки пар ключ / значение.
В заказе необходимо помнить подробности о том, какие продукты были заказаны, сколько и на какую сумму. Для этого нужна еще одна промежуточная модель: ProductOrder.
Базовые модели будут выглядеть примерно так:
class Product < ApplicationRecord
belongs_to :shop
has_many :product_orders
has_many :orders, through: :product_orders
has_many :customers, through: :orders
# name
# description
# sku
end
class Shop < ApplicationRecord
has_many :products
has_many :marketplace_accounts
has_many :marketplaces, through: :marketplace_accounts
has_many :orders
has_many :customers, through: :orders
# name
# country
end
class Order < ApplicationRecord
belongs_to :customer
# Remember which MarketplaceAccount this was done with
belongs_to :marketplace_account
has_one :shop, through: :marketplace_account
has_one :marketplace, through: :marketplace_account
# How is it being shipped?
belongs_to :shipping_method
has_many :product_orders
has_many :products, through: :product_orders
# tracking number
# status
end
class ProductOrder < ApplicationRecord
belongs_to :order
belongs_to :product
# price
# quantity
end
# Holds the Shop's credentials for a Marketplace.
class MarketplaceAccount < ApplicationRecord
belongs_to :shop
belongs_to :marketplace
has_many :credentials
end
# Each row is simply a key and value.
# Consider encrypting this table.
class Credentials < ApplicationRecord
belongs_to :marketplace_account
# key
# value
end
class Marketplace < ApplicationRecord
has_many :shipping_methods
has_many :marketplace_accounts
has_many :shops, through: :marketplace_accounts
# name
end
class ShippingMethod < ApplicationRecord
belongs_to :marketplace
has_many :shops, through: :marketplace
# speed
# rate
# name
end
class Customer < ApplicationRecord
has_many :orders
has_many :product_orders, through: :orders
has_many :products, through: :product_orders
end
Используя has_many :through
и has_one :through
, мы можем избежать дублирования, делая косвенные отношения кажущимися прямыми. У магазина есть множество учетных записей MarketplaceAccounts, учетная запись MarketplaceAccount принадлежит торговой площадке; при has_many :marketplaces, through: :marketplace_accounts
этом магазин может напрямую обращаться к своим торговым площадкам. shop.marketplaces
.
Таблица учетных данных ключ/значение позволяет избежать увеличения количества таблиц учетных данных, специфичных для конкретной компании.
Можно конкретизировать больше взаимосвязей. Продукт может продаваться многими магазинами, поэтому у нас может быть ShopProduct, который связывает универсальный продукт с тем, как его продает Магазин. Это позволяет избежать дублирования информации о продукте и позволяет увидеть, как один продукт продается во многих магазинах.
class Product < ApplicationRecord
has_many :shop_products
# sku
# generic name
# generic description
# manufacturer's recommended price
end
class ShopProduct < ApplicationRecord
belongs_to :shop
belongs_to :product
delegate :sku, to: :product
# shop specific name
# shop specific description
# shop price
end
class Shop
has_many :shop_products
has_many :products, through: :shop_products
end
И большинство вещей будут относиться к Товару, а не к Продукту.
У вас есть магазин, работающий с единой валютой. Дизайн может быть расширен, чтобы позволить магазину работать со многими валютами.
class Currency < ApplicationRecord
# symbol
# conversion rate
end
class ShopCurrencies < ApplicationRecord
belongs_to :shop
belongs_to :currency
end
class Shop < ApplicationRecord
has_many :shop_currencies
has_many :currencies, through: :shop_currencies
end
has_many :currencies, through: :shop_currencies
давайте shop.currencies
работать.
Это основы. Вооружившись этим, вы можете настроить базовый макет в соответствии с вашими потребностями.
Комментарии:
1. большое спасибо за подробный ответ!