Receber por email
← Voltar para o catálogo

spree-data-model

Navigate Spree's canonical data model — the Catalog (Product/Variant/OptionType/Taxon/Property/Metafield), Pricing (Price/PriceList), Order graph (Order/LineItem/Adjustment/Shipment/Payment/PaymentSession/Refund/Reimbursement), Inventory (StockLocation/StockItem/StockMovement), Shipping (ShippingMethod/Zone), Promotions, Identity (User/Role/Address/StoreCredit/GiftCard), Taxes, and the v5.4+ Marke

34estrelas
Atualizado há 5 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add OrcaQubits/agentic-commerce-skills-plugins

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/spree-data-model/svg)](https://www.skillteca.com.br/skills/spree-data-model)

Skills relacionadas

Ver todas de Dados e Análise →

Alerta por categoria

Receba novas skills de Dados e Análise toda segunda

1 email curto, só com as skills novas de Dados e Análise. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Spree Data Model

Before writing code

Fetch live docs:

  1. Fetch https://spreecommerce.org/docs/developer/core-concepts/architecture for the current model graph.
  2. Fetch https://spreecommerce.org/docs/developer/core-concepts/orders for the Order/LineItem/Payment/Shipment graph and state.
  3. Fetch https://spreecommerce.org/docs/developer/core-concepts/metafields for Metafield (v5+).
  4. Fetch https://spreecommerce.org/docs/use-case/multi-store/model for Store and Market.
  5. Inspect the live spree gem source on GitHub for current column names — Spree adds columns between minors.

Conceptual Architecture

Catalog

| Model | Purpose | Notes | |-------|---------|-------| | Product | Top-level catalog item | Has a master Variant; many Images, Propertys, Taxons | | Variant | Concrete SKU | Has OptionValues, Prices per currency, StockItems | | OptionType / OptionValue | Variant axes (size, color) | An OptionType has many OptionValues | | Property / ProductProperty | Free-form spec table | "Material: cotton", "Weight: 250g" | | Taxonomy / Taxon | Category trees | Taxon is the nested-set node | | Image / Asset | Media | Uses ActiveStorage | | Metafield | Custom data on any model (v5+) | Like Shopify metafields |

Pricing

| Model | Purpose | |-------|---------| | Price | One row per (Variant × Currency) | | PriceList (v5.3+) | Override prices for a customer group, store, or country | | Calculator | Polymorphic calculator class for shipping/promotion/tax math |

Order Graph

Order
├── LineItem (one per Variant)
│   └── Adjustment[]
├── Shipment (one per StockLocation involved)
│   ├── InventoryUnit
│   ├── ShippingRate
│   └── selected ShippingRate
├── Payment[]
│   ├── PaymentSession (v5.4+, provider-agnostic envelope)
│   └── source (CreditCard, StoreCredit, etc.)
├── Adjustment[] (order-level)
├── Address (bill_address, ship_address)
└── User (optional — guest orders allowed)

Plus return-flow models: ReturnAuthorization → CustomerReturn → Reimbursement → Refund.

Inventory

  • StockLocation — physical / logical warehouse
  • StockItem — count of a Variant in a StockLocation
  • StockMovement — append-only ledger of stock changes
  • StockTransfer — moves stock between locations

Shipping

  • ShippingMethod — names a way to ship (UPS Ground, Express)
  • ShippingRate — computed cost option on a Shipment
  • ShippingCategory — categorize products by shipping needs
  • Zone / ZoneMember — countries/states a method ships to

Promotions

Promotion + PromotionRule + PromotionAction + CouponCode resulting in Adjustments.

Identity

| Model | Notes | |-------|-------| | User | Spree's customer / admin model (Devise-backed in v5+) | | Role | Permissions — admin, customer, custom | | Address | Bill / ship address, optionally tied to a user | | StoreCredit | Balance on a user, usable as payment | | GiftCard | Tradeable balance, redeemable as payment method | | CustomerGroup | Segments for pricing / promotions | | Invitation | Invite to an account | | ApiKey | Per-user API key for v3 admin API |

Taxes

  • TaxCategory — assignable to products (e.g., "Clothing", "Books")
  • TaxRate — percentage by Zone + TaxCategory

Multi-Store / Region

| Model | Purpose | |-------|---------| | Store | One install → many stores, each with own domain/theme/policies | | Market (v5.4+) | Bundles currency + locale + payment methods + shipping per region | | CmsPage | Content pages per store | | Theme | Storefront theme per store |

Shared across stores: products, inventory, customers, shipping methods, payment gateways, Markets, admin roles. Per-store: orders, shipments, payments, refunds, store credits, gift cards, themes, blogs, pages, integrations.

Spree::Metafield (v5+)

A flexible custom-data system attached to any model. Replaces ad-hoc decorators for "I just need one extra field." Use this before adding a column.

prefixed IDs (v5.4+)

API v3 exposes prefixed IDs (prod_…, ord_…, var_…, usr_…, pay_…) — these are stable string identifiers separate from the database id. Models gain a prefixed_id method.

Polymorphic Adjustments

Adjustment belongs to an adjustable (Order, LineItem, Shipment) and a source (PromotionAction, TaxRate, manual). When sums change, run order.update_totals or use Spree::OrderUpdater (or its swappable replacement via Spree::Dependencies).

Implementation Guidance

Querying Safely in Multi-Store

# WRONG — leaks across stores
Spree::Order.complete

# RIGHT — always scope by current_store in customer-facing code
current_store.orders.complete

# Admin-side: admin sees all stores by default, but check role scoping
Spree::Order.where(store_id: current_store.id)

Reading Variants With Their Pricing

variant = Spree::Variant.find(...)
variant.price_in('USD').amount    # raw decimal
variant.price_in('USD').display_price  # formatted "$19.99"
variant.amount_in('USD')          # alias for price_in(currency).amount

For v5.3+ PriceList overrides:

price = Spree::Pricing::PriceFinder.new(variant: variant, store: store, user: user, currency: 'USD').call

(Verify the live API — pricing service objects are routinely renamed.)

Order Totals

Don't recompute totals manually. Use the order updater service:

Spree::OrderUpdater.new(order).update
# or via Dependencies
Spree::Dependencies.order_updater.call(order)

Adding Custom Data Without a Decorator

Prefer Metafield over adding columns:

product.metafields.create!(
  namespace: 'my_app',
  key: 'launch_date',
  value: '2026-06-01',
  value_type: 'string'
)
product.metafield('my_app', 'launch_date')

Verify the exact API in the live metafields doc.

Designing for the Order Graph

  • One Order has many Shipments when items come from different StockLocations.
  • One Shipment has many InventoryUnits — one per unit sold.
  • Payments are not necessarily 1:1 with orders — split tender (store credit + card) creates multiple Payments.
  • PaymentSessions (v5.4+) wrap a Payment for provider-agnostic checkout flows.

Common Pitfalls

  • Modifying Order totals directly — always recompute via the updater service.
  • Adding columns when a Metafield would do — Metafields don't need migrations and survive upgrades.
  • Ignoring Store#default — most APIs default to it, but explicit scoping is safer.
  • Adjustments on canceled lines — when a line item is removed mid-order, adjustments tied to it need explicit cleanup. Use service objects, not raw delete.
  • Assuming Variant.is_master ordering — the master variant is always present; option-variant ordering follows position columns.

Always cross-check column names and relationships against the live source — the data model evolves between minor releases.

Compartilhar X LinkedIn