Back to Spree

Store API Naming Standardization

docs/plans/5.4-store-api-naming-standardization.md

5.4.211.7 KB
Original Source

Store API Naming Standardization

Status: In Progress Target: Spree 5.4 (API surface + model aliases); Spree 6.0 (database columns/tables) Depends on: 5.4-store-api-bridges.md (same pattern: rename API surface now, models/DB later) Author: Damian + Claude Last updated: 2026-03-19

Summary

Standardize Spree Store API entity and attribute names against industry conventions (Shopify, Medusa, Saleor, Vendure, BigCommerce, commercetools). Changes follow the established bridge pattern: rename serializers, controllers, and add model aliases now (5.4), defer database column/table renames to 6.0.

Key Decisions (do not deviate without discussion)

  • All changes are breaking in the Store API — no backward compatibility, new names only (same approach as 5.4-store-api-bridges.md)
  • Models get alias accessors for new names pointing to old columns — serializers and services use the new names directly
  • Database column/table renames are deferred to 6.0
  • Controllers accept new param names only — no backward compat for old names

Changes

1. Address: ship_address / bill_addressshipping_address / billing_address

Serializers: Cart and Order serializers use key: :billing_address / key: :shipping_address on the association.

Controllers: Cart update accepts shipping_address_id, billing_address_id, shipping_address: {}, billing_address: {}.

Service: Carts::Update uses assign_address(:shipping_address) / :billing_address directly.

Model aliases (already existed + new):

  • alias_method :billing_address, :bill_address (existed)
  • alias_method :shipping_address, :ship_address (existed)
  • alias_attribute :billing_address_id, :bill_address_id (new)
  • alias_attribute :shipping_address_id, :ship_address_id (new)
  • alias shipping_address_attributes= ship_address_attributes= (new)
  • alias billing_address_attributes= bill_address_attributes= (new)

6.0 database: Rename spree_orders.bill_address_idbilling_address_id, spree_orders.ship_address_idshipping_address_id

2. Address: firstname/lastnamefirst_name/last_name

Serializer: AddressSerializer exposes first_name / last_name.

Controllers: Accept first_name / last_name only.

Model (already existed): Spree::Address has first_name / last_name accessor methods and Spree::PermittedAttributes includes both forms.

6.0 database: Rename spree_addresses.firstnamefirst_name, spree_addresses.lastnamelast_name

3. Address: zipcodepostal_code

Serializer: AddressSerializer exposes postal_code.

Controllers: Accept postal_code only.

Model (already existed): alias_attribute :postal_code, :zipcode on Spree::Address.

6.0 database: Rename spree_addresses.zipcodepostal_code

4. CartPromotion/OrderPromotion → Discount

Serializers:

  • Created DiscountSerializer (single serializer for both cart and order promotions)
  • Deleted CartPromotionSerializer and OrderPromotionSerializer files
  • Cart/Order serializers: key: :discounts on the association
  • Admin: Admin::DiscountSerializer replaces Admin::OrderPromotionSerializer

Model aliases: alias discounts order_promotions on Spree::Order

Dependencies: discount_serializer, cart_promotion_serializer, order_promotion_serializer all point to DiscountSerializer. Admin: admin_discount_serializer and admin_order_promotion_serializer point to Admin::DiscountSerializer.

TypeScript type: CartPromotion / OrderPromotionDiscount

5. promo_totaldiscount_total

Serializers: Cart, Order, LineItem serializers expose discount_total / display_discount_total.

Model aliases:

  • Spree::Order: alias_attribute :discount_total, :promo_total, alias display_discount_total display_promo_total
  • Spree::LineItem: alias_attribute :discount_total, :promo_total, alias display_discount_total display_promo_total

6.0 database: Rename spree_orders.promo_totaldiscount_total, spree_line_items.promo_totaldiscount_total

6. WishedItem → WishlistItem

Serializers: Created WishlistItemSerializer, WishlistSerializer references it. Old WishedItemSerializer kept for now (dependency points to new one).

Model alias: alias wishlist_items wished_items on Spree::Wishlist

Dependencies: wishlist_item_serializer and wished_item_serializer both point to WishlistItemSerializer.

6.0 database/model: Rename Spree::WishedItemSpree::WishlistItem, table spree_wished_itemsspree_wishlist_items, prefix wi_wli_

7. special_instructionscustomer_note

Serializers: Cart and Order serializers expose customer_note.

Controller: Cart update accepts customer_note only.

Service: Carts::Update assigns cart.customer_note.

Model alias: alias_attribute :customer_note, :special_instructions on Spree::Order

6.0 database: Rename spree_orders.special_instructionscustomer_note

8. OptionType/OptionValue: presentationlabel

Serializers: OptionTypeSerializer and OptionValueSerializer expose label. OptionValueSerializer exposes option_type_label.

Model aliases: alias_attribute :label, :presentation on both Spree::OptionType and Spree::OptionValue

6.0 database: Rename spree_option_types.presentationlabel, spree_option_values.presentationlabel

9. Remove Asset serializer from Store API

AssetSerializer excluded from Store SDK types via Typelizer reject_class filter. Media serializer is the correct Store-facing entity.

10. Exclude admin-only schemas from Store API types

Added Typelizer reject_class filter excluding serializers with no Store API controller: Asset, CartPromotion, OrderPromotion, StockItem, StockMovement, StockTransfer, ShippingCategory, Reimbursement, Report, Export, Import, ImportRow, TaxCategory, CustomerReturn

11. Slim down Promotion serializer for Store API

PromotionSerializer reduced to: id, name, description, code. Full promotion details remain in Admin serializer only.

12. CreditCard: cc_typebrand, last_digitslast4

Serializer: CreditCardSerializer exposes brand and last4.

Model aliases:

  • alias_attribute :brand, :cc_type (already existed)
  • alias_attribute :last4, :last_digits (new)

6.0 database: Rename spree_credit_cards.cc_typebrand, spree_credit_cards.last_digitslast4

13. Remove gateway_payment_profile_id from Store API

Removed from CreditCardSerializer and PaymentSourceSerializer. Added to Admin::CreditCardSerializer and Admin::PaymentSourceSerializer.

14. item_counttotal_quantity

Serializers: Cart and Order serializers expose total_quantity.

Model alias: alias_attribute :total_quantity, :item_count on Spree::Order

6.0 database: Rename spree_orders.item_counttotal_quantity

15. ReturnAuthorization: statestatus

Serializer: ReturnAuthorizationSerializer exposes status (reads object.state).

6.0 database: Covered by 6.0-normalize-state-to-status.md

16. Additional Order model aliases (from 5.4-store-api-bridges)

These aliases consolidate all naming bridges on Spree::Order:

  • alias fulfillments shipments
  • alias_attribute :delivery_total, :shipment_total
  • alias display_delivery_total display_shipment_total
  • alias_attribute :fulfillment_status, :shipment_state
  • alias_attribute :payment_status, :payment_state

Implementation Status

Files created

  • api/app/serializers/spree/api/v3/discount_serializer.rb
  • api/app/serializers/spree/api/v3/wishlist_item_serializer.rb
  • api/app/serializers/spree/api/v3/admin/discount_serializer.rb

Files deleted

  • api/app/serializers/spree/api/v3/cart_promotion_serializer.rb
  • api/app/serializers/spree/api/v3/order_promotion_serializer.rb
  • api/app/serializers/spree/api/v3/admin/order_promotion_serializer.rb

Files modified

  • api/app/serializers/spree/api/v3/address_serializer.rbfirstnamefirst_name, lastnamelast_name, zipcodepostal_code
  • api/app/serializers/spree/api/v3/cart_serializer.rb — all renames (customer_note, total_quantity, discount_total, billing/shipping_address, discounts)
  • api/app/serializers/spree/api/v3/order_serializer.rb — same as cart
  • api/app/serializers/spree/api/v3/line_item_serializer.rbpromo_totaldiscount_total
  • api/app/serializers/spree/api/v3/option_type_serializer.rbpresentationlabel
  • api/app/serializers/spree/api/v3/option_value_serializer.rbpresentationlabel, option_type_presentationoption_type_label
  • api/app/serializers/spree/api/v3/credit_card_serializer.rbcc_typebrand, last_digitslast4, removed gateway_payment_profile_id
  • api/app/serializers/spree/api/v3/payment_source_serializer.rb — removed gateway_payment_profile_id
  • api/app/serializers/spree/api/v3/return_authorization_serializer.rbstatestatus
  • api/app/serializers/spree/api/v3/promotion_serializer.rb — slimmed to name/description/code
  • api/app/serializers/spree/api/v3/wishlist_serializer.rb — references wishlist_item_serializer
  • api/app/serializers/spree/api/v3/admin/order_serializer.rb — discounts key, billing/shipping_address keys, admin_discount_serializer
  • api/app/serializers/spree/api/v3/admin/credit_card_serializer.rb — added gateway_payment_profile_id
  • api/app/serializers/spree/api/v3/admin/payment_source_serializer.rb — added gateway_payment_profile_id
  • api/app/controllers/spree/api/v3/store/carts_controller.rb — new param names only
  • api/app/controllers/spree/api/v3/store/customer/addresses_controller.rb — new param names only
  • api/lib/spree/api/dependencies.rb — added discount_serializer, wishlist_item_serializer, admin_discount_serializer
  • api/config/initializers/typelizer.rb — exclude admin-only schemas from Store types
  • core/app/models/spree/order.rb — all aliases (discount_total, customer_note, total_quantity, billing/shipping_address_id, discounts, fulfillments, etc.)
  • core/app/models/spree/line_item.rb — discount_total alias
  • core/app/models/spree/option_type.rb — label alias
  • core/app/models/spree/option_value.rb — label alias
  • core/app/models/spree/credit_card.rb — last4 alias
  • core/app/models/spree/wishlist.rb — wishlist_items alias
  • core/app/services/spree/carts/update.rb — uses new names (shipping_address, billing_address, customer_note)

Integration tests updated

  • api/spec/integration/spree/api/v3/store/carts_spec.rb
  • api/spec/integration/spree/api/v3/store/addresses_spec.rb
  • api/spec/integration/spree/api/v3/store/credit_cards_spec.rb

Test results

  • Backend integration tests: 149/149 pass

Still TODO

  • Regenerate TypeScript types (bundle exec rake typelizer:generate)
  • Regenerate Zod schemas (cd packages/sdk && pnpm generate:zod)
  • Update SDK client code and tests
  • Update Next.js package
  • Regenerate OpenAPI spec (bundle exec rake rswag:specs:swaggerize)
  • Update docs

Constraints on Current Work

  • All new Store API code must use the new naming from this plan
  • Admin API inherits Store serializer renames via inheritance — Admin serializer keys also use new names
  • SDK examples and docs must use new naming after this ships

Open Questions

None — all decisions made.

References

  • 5.4-store-api-bridges.md — prior art for this exact pattern
  • 6.0-normalize-state-to-status.md — covers statestatus DB rename
  • Industry comparison: Shopify, Medusa, Saleor, Vendure, BigCommerce, commercetools Storefront APIs