Skip to content

Instantly share code, notes, and snippets.

@louishuyng
Created October 24, 2023 15:28
Show Gist options
  • Save louishuyng/b6f58c8c3462d3e37868d76e3471db42 to your computer and use it in GitHub Desktop.
Save louishuyng/b6f58c8c3462d3e37868d76e3471db42 to your computer and use it in GitHub Desktop.
Aggregate Root
class Product
include AggregateRoot
def register(store_id:, sku:)
apply(ProductRegistered.new(data: {
store_id: store_id,
sku: sku,
}))
end
def supply(quantity)
apply(ProductSupplied.new(data: {
store_id: @store_id,
sku: @sku,
quantity: quantity,
}))
end
def reserve(quantity:, order_number:)
unless @quantity_available >= quantity
raise QuantityNotAvailable
end
apply(ProductReserved.new(data: {
store_id: @store_id,
sku: @sku,
quantity: quantity,
order_number: order_number,
}))
end
private
def apply_strategy
->(_me, event) do
case event
when ProductRegistered
registered(event)
when ProductSupplied
supplied(event)
when ProductReserved
reserved(event)
else
raise "Missing handler for #{event}"
end
end
end
def registered(event)
@store_id = event.data.fetch(:store_id)
@sku = event.data.fetch(:sku)
@quantity_available = 0
@quantity_reserved = 0
@quantity_shipped = 0
end
def supplied(event)
@quantity_available += event.data.fetch(:quantity)
end
def reserved(event)
quantity = event.data.fetch(:quantity)
@quantity_available -= quantity
@quantity_reserved += quantity
end
end
repository = AggregateRoot::Repository.new(Rails.configuration.event_store)
stream = "Product$#{product_id}"
product = repository.load(Product.new, stream)
product.reserve(
quantity: quantity,
order_number: order_number
)
repository.store(product, stream)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment