Skip to content

Commit

Permalink
Functional goes objects
Browse files Browse the repository at this point in the history
Co-authored-by: Szymon Fiedler <[email protected]>
Co-authored-by: Piotr Jurewicz <[email protected]>
  • Loading branch information
3 people committed Nov 22, 2023
1 parent 568665f commit 377b24a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 43 deletions.
23 changes: 12 additions & 11 deletions examples/decider/lib/project_management/command_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ module ProjectManagement
class CommandHandler
def initialize(event_store)
@event_store = event_store
@decider = Issue
end

def handle(cmd)
state, version =
@event_store
.read
.stream(stream_name(cmd.id))
.reduce(
[@decider.initial_state(cmd.id), -1]
) do |(state, version), event|
[@decider.evolve(state, event), version + 1]
end
decider = Issue.new(cmd.id)
version = -1

case result = @decider.decide(cmd, state)
@event_store
.read
.stream(stream_name(cmd.id))
.each
.with_index do |event, idx|
decider.evolve(event)
version = idx
end

case result = decider.decide(cmd)
when StandardError
raise Error
else
Expand Down
70 changes: 38 additions & 32 deletions examples/decider/lib/project_management/issue.rb
Original file line number Diff line number Diff line change
@@ -1,68 +1,74 @@
module ProjectManagement
module Issue
class Issue
InvalidTransition = Class.new(StandardError)
State = Data.define(:id, :status)
private_constant :State

def self.decide(command, state)
def initialize(id)
@state = initial_state(id)
end

def decide(command)
case command
when CreateIssue
if state.status
if @state.status
InvalidTransition.new
else
IssueOpened.new(data: { issue_id: state.id })
IssueOpened.new(data: { issue_id: @state.id })
end
when ResolveIssue
if %i[open in_progress reopened].include? state.status
IssueResolved.new(data: { issue_id: state.id })
if %i[open in_progress reopened].include? @state.status
IssueResolved.new(data: { issue_id: @state.id })
else
InvalidTransition.new
end
when CloseIssue
if %i[open in_progress resolved reopened].include? state.status
IssueClosed.new(data: { issue_id: state.id })
if %i[open in_progress resolved reopened].include? @state.status
IssueClosed.new(data: { issue_id: @state.id })
else
InvalidTransition.new
end
when ReopenIssue
if %i[resolved closed].include? state.status
IssueReopened.new(data: { issue_id: state.id })
if %i[resolved closed].include? @state.status
IssueReopened.new(data: { issue_id: @state.id })
else
InvalidTransition.new
end
when StartIssueProgress
if %i[open reopened].include? state.status
IssueProgressStarted.new(data: { issue_id: state.id })
if %i[open reopened].include? @state.status
IssueProgressStarted.new(data: { issue_id: @state.id })
else
InvalidTransition.new
end
when StopIssueProgress
if %i[in_progress].include? state.status
IssueProgressStopped.new(data: { issue_id: state.id })
if %i[in_progress].include? @state.status
IssueProgressStopped.new(data: { issue_id: @state.id })
else
InvalidTransition.new
end
end
end

def self.evolve(state, event)
case event
when IssueOpened
state.with(status: :open)
when IssueResolved
state.with(status: :resolved)
when IssueClosed
state.with(status: :closed)
when IssueReopened
state.with(status: :reopened)
when IssueProgressStarted
state.with(status: :in_progress)
when IssueProgressStopped
state.with(status: :open)
end
def evolve(event)
@state =
case event
when IssueOpened
@state.with(status: :open)
when IssueResolved
@state.with(status: :resolved)
when IssueClosed
@state.with(status: :closed)
when IssueReopened
@state.with(status: :reopened)
when IssueProgressStarted
@state.with(status: :in_progress)
when IssueProgressStopped
@state.with(status: :open)
end
end

def self.initial_state(id)
State.new(id: id, status: nil)
end
private

def initial_state(id) = State.new(id: id, status: nil)
end
end

0 comments on commit 377b24a

Please sign in to comment.