Skip to content

Commit 5aa43f8

Browse files
committed
A different way to move ProcessState definition to the bottom of a process class.
This way include is on the very top of the class definition, ProcessState is passed in a block that is called later. The ProcessState definition can be moved to the very bottom of the class. - pass a block to the with_state method - the block is stored in the module ivar and then in the host class ivar - the block is called during initial_state method execution, ProcssState has to be defined at this point
1 parent dd47698 commit 5aa43f8

File tree

7 files changed

+75
-66
lines changed

7 files changed

+75
-66
lines changed

ecommerce/processes/lib/processes/determine_vat_rates_on_order_placed.rb

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
module Processes
22
class DetermineVatRatesOnOrderPlaced
3+
include Infra::ProcessManager.with_state { ProcessState }
34

4-
ProcessState = Data.define(:offer_accepted, :order_placed, :order_id, :order_lines) do
5-
def initialize(offer_accepted: false, order_placed: false, order_id: nil, order_lines: [])
6-
super
7-
end
8-
9-
def placed? = offer_accepted && order_placed
10-
end
11-
12-
include Infra::ProcessManager.with_state(ProcessState)
135
subscribes_to(
146
Pricing::OfferAccepted,
157
Fulfillment::OrderRegistered
@@ -46,5 +38,12 @@ def fetch_id(event)
4638
event.data.fetch(:order_id)
4739
end
4840

41+
ProcessState = Data.define(:offer_accepted, :order_placed, :order_id, :order_lines) do
42+
def initialize(offer_accepted: false, order_placed: false, order_id: nil, order_lines: [])
43+
super
44+
end
45+
46+
def placed? = offer_accepted && order_placed
47+
end
4948
end
5049
end

ecommerce/processes/lib/processes/order_item_invoicing_process.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
module Processes
22
class OrderItemInvoicingProcess
3-
4-
ProcessState = Data.define(:order_id, :product_id, :quantity, :vat_rate, :discounted_amount) do
5-
def initialize(order_id: nil, product_id: nil, quantity: nil, vat_rate: nil, discounted_amount: nil)
6-
super
7-
end
8-
9-
def can_create_invoice_item?
10-
order_id && product_id && quantity && vat_rate && discounted_amount
11-
end
12-
end
13-
14-
include Infra::ProcessManager.with_state(ProcessState)
3+
include Infra::ProcessManager.with_state { ProcessState }
154

165
subscribes_to(
176
Pricing::PriceItemValueCalculated,
@@ -56,6 +45,16 @@ def apply(event)
5645
def fetch_id(event)
5746
"#{event.data.fetch(:order_id)}$#{event.data.fetch(:product_id)}"
5847
end
48+
49+
ProcessState = Data.define(:order_id, :product_id, :quantity, :vat_rate, :discounted_amount) do
50+
def initialize(order_id: nil, product_id: nil, quantity: nil, vat_rate: nil, discounted_amount: nil)
51+
super
52+
end
53+
54+
def can_create_invoice_item?
55+
order_id && product_id && quantity && vat_rate && discounted_amount
56+
end
57+
end
5958
end
6059

6160
class MoneySplitter

ecommerce/processes/lib/processes/release_payment_process.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
module Processes
22
class ReleasePaymentProcess
3-
4-
ProcessState = Data.define(:order, :payment, :order_id) do
5-
def initialize(order: :draft, payment: :none, order_id: nil)
6-
super
7-
end
8-
9-
def release?
10-
payment.eql?(:authorized) && order.eql?(:expired)
11-
end
12-
end
13-
14-
include Infra::ProcessManager.with_state(ProcessState)
3+
include Infra::ProcessManager.with_state { ProcessState }
154

165
subscribes_to(
176
Payments::PaymentAuthorized,
@@ -52,5 +41,15 @@ def release_payment
5241
def fetch_id(event)
5342
event.data.fetch(:order_id)
5443
end
44+
45+
ProcessState = Data.define(:order, :payment, :order_id) do
46+
def initialize(order: :draft, payment: :none, order_id: nil)
47+
super
48+
end
49+
50+
def release?
51+
payment.eql?(:authorized) && order.eql?(:expired)
52+
end
53+
end
5554
end
5655
end

ecommerce/processes/lib/processes/reservation_process.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
module Processes
22
class ReservationProcess
3-
ProcessState = Data.define(:order, :order_lines) do
4-
def initialize(order: nil, order_lines: [])
5-
super(order:, order_lines: order_lines.freeze)
6-
end
7-
8-
def reserved_product_ids = order_lines.keys
9-
end
10-
11-
include Infra::ProcessManager.with_state(ProcessState)
3+
include Infra::ProcessManager.with_state { ProcessState }
124

135
subscribes_to(
146
Pricing::OfferAccepted,
@@ -92,6 +84,14 @@ def fetch_id(event)
9284
event.data.fetch(:order_id)
9385
end
9486

87+
ProcessState = Data.define(:order, :order_lines) do
88+
def initialize(order: nil, order_lines: [])
89+
super(order:, order_lines: order_lines.freeze)
90+
end
91+
92+
def reserved_product_ids = order_lines.keys
93+
end
94+
9595
class SomeInventoryNotAvailable < StandardError
9696
attr_reader :unavailable_products
9797

ecommerce/processes/lib/processes/shipment_process.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
module Processes
22
class ShipmentProcess
3-
ProcessState = Data.define(:order, :shipment) do
4-
def initialize(order: nil, shipment: nil) = super
5-
end
6-
7-
include Infra::ProcessManager.with_state(ProcessState)
3+
include Infra::ProcessManager.with_state { ProcessState }
84

95
subscribes_to(
106
Shipping::ShippingAddressAddedToShipment,
@@ -47,5 +43,9 @@ def authorize_shipment
4743
def fetch_id(event)
4844
event.data.fetch(:order_id)
4945
end
46+
47+
ProcessState = Data.define(:order, :shipment) do
48+
def initialize(order: nil, shipment: nil) = super
49+
end
5050
end
5151
end

ecommerce/processes/lib/processes/three_plus_one_free.rb

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,6 @@
11
module Processes
22
class ThreePlusOneFree
3-
4-
ProcessState = Data.define(:lines, :free_product) do
5-
def initialize(lines: [], free_product: nil)
6-
super(lines: lines.freeze, free_product:)
7-
end
8-
9-
MIN_ORDER_LINES_QUANTITY = 4
10-
11-
def eligible_free_product
12-
if lines.size >= MIN_ORDER_LINES_QUANTITY
13-
lines.sort_by { _1.fetch(:price) }.first.fetch(:product_id)
14-
end
15-
end
16-
end
17-
18-
include Infra::ProcessManager.with_state(ProcessState)
3+
include Infra::ProcessManager.with_state { ProcessState }
194

205
subscribes_to(
216
Pricing::PriceItemAdded,
@@ -66,5 +51,19 @@ def make_new_product_for_free(product_id)
6651
def fetch_id(event)
6752
event.data.fetch(:order_id)
6853
end
54+
55+
ProcessState = Data.define(:lines, :free_product) do
56+
def initialize(lines: [], free_product: nil)
57+
super(lines: lines.freeze, free_product:)
58+
end
59+
60+
MIN_ORDER_LINES_QUANTITY = 4
61+
62+
def eligible_free_product
63+
if lines.size >= MIN_ORDER_LINES_QUANTITY
64+
lines.sort_by { _1.fetch(:price) }.first.fetch(:product_id)
65+
end
66+
end
67+
end
6968
end
7069
end

infra/lib/infra/process_manager.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,31 @@ def subscribes_to(*events)
4343
attr_reader :subscribed_events
4444
end
4545

46-
def self.with_state(state_class)
46+
def self.with_state(&state_class_block)
47+
unless block_given?
48+
raise ArgumentError, "A block returning the state class is required."
49+
end
4750

4851
Module.new do
49-
define_method :initial_state do
52+
@state_definition_block = state_class_block
53+
54+
define_method(:initial_state) do
55+
block = self.class.instance_variable_get(:@state_definition_block)
56+
raise "State definition block not found on #{self.class}" unless block
57+
58+
state_class = block.call
59+
raise "State definition block did not return a Class" unless state_class.is_a?(Class)
60+
5061
state_class.new
5162
end
5263

53-
def state
64+
define_method(:state) do
5465
@state ||= initial_state
5566
end
5667

5768
def self.included(host_class)
69+
host_class.instance_variable_set(:@state_definition_block, @state_definition_block)
70+
5871
host_class.include(ProcessMethods)
5972
host_class.include(Infra::Retry)
6073
host_class.extend(Subscriptions)

0 commit comments

Comments
 (0)