Class: BetterService::Workflows::Branch

Inherits:
Object
  • Object
show all
Defined in:
lib/better_service/workflows/branch.rb

Overview

Represents a single conditional branch within a workflow

A Branch contains:

  • A condition (Proc) that determines if the branch should execute

  • An array of steps to execute if the condition is true

  • An optional name for identification

Examples:

branch = Branch.new(
  condition: ->(ctx) { ctx.user.premium? },
  name: :premium_path
)
branch.add_step(step1)
branch.add_step(step2)

if branch.matches?(context)
  branch.execute(context, user, params)
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(condition: nil, name: nil) ⇒ Branch

Creates a new Branch

Parameters:

  • condition (Proc, nil) (defaults to: nil)

    The condition to evaluate (nil for default/otherwise branch)

  • name (Symbol, nil) (defaults to: nil)

    Optional name for the branch



30
31
32
33
34
# File 'lib/better_service/workflows/branch.rb', line 30

def initialize(condition: nil, name: nil)
  @condition = condition
  @steps = []
  @name = name
end

Instance Attribute Details

#conditionObject (readonly)

Returns the value of attribute condition.



24
25
26
# File 'lib/better_service/workflows/branch.rb', line 24

def condition
  @condition
end

#nameObject (readonly)

Returns the value of attribute name.



24
25
26
# File 'lib/better_service/workflows/branch.rb', line 24

def name
  @name
end

#stepsObject (readonly)

Returns the value of attribute steps.



24
25
26
# File 'lib/better_service/workflows/branch.rb', line 24

def steps
  @steps
end

Instance Method Details

#add_step(step) ⇒ Array

Adds a step to this branch

Parameters:

Returns:

  • (Array)

    The updated steps array



57
58
59
# File 'lib/better_service/workflows/branch.rb', line 57

def add_step(step)
  @steps << step
end

#default?Boolean

Returns whether this is a default branch (no condition)

Returns:

  • (Boolean)


119
120
121
# File 'lib/better_service/workflows/branch.rb', line 119

def default?
  condition.nil?
end

#execute(context, user, params, branch_decisions = nil) ⇒ Array<Workflowable::Step>

Executes all steps in this branch

Parameters:

  • context (Workflowable::Context)

    The workflow context

  • user (Object)

    The current user

  • params (Hash)

    The workflow parameters

  • branch_decisions (Array, nil) (defaults to: nil)

    Array to track branch decisions for nested branches

Returns:

Raises:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/better_service/workflows/branch.rb', line 69

def execute(context, user, params, branch_decisions = nil)
  executed_steps = []

  @steps.each do |step_or_branch_group|
    # Handle nested BranchGroup
    if step_or_branch_group.is_a?(BranchGroup)
      branch_result = step_or_branch_group.call(context, user, params)

      # Add executed steps from nested branch
      if branch_result[:executed_steps]
        executed_steps.concat(branch_result[:executed_steps])
      end

      # Track nested branch decisions
      if branch_decisions && branch_result[:branch_decisions]
        branch_decisions.concat(branch_result[:branch_decisions])
      end

      next
    end

    # Handle regular Step
    result = step_or_branch_group.call(context, user, params)

    # Skip if step was skipped
    next if result[:skipped]

    # Handle step failure
    if result[:success] == false && !result[:optional_failure]
      raise Errors::Workflowable::Runtime::StepExecutionError.new(
        "Step #{step_or_branch_group.name} failed in branch",
        code: ErrorCodes::STEP_FAILED,
        context: {
          step: step_or_branch_group.name,
          branch: @name,
          errors: result[:errors]
        }
      )
    end

    # Track successfully executed steps
    executed_steps << step_or_branch_group unless result[:optional_failure]
  end

  executed_steps
end

#inspectString

Returns a string representation of this branch

Returns:

  • (String)


126
127
128
129
130
# File 'lib/better_service/workflows/branch.rb', line 126

def inspect
  "#<BetterService::Workflows::Branch name=#{@name.inspect} " \
    "condition=#{@condition.present? ? 'present' : 'nil'} " \
    "steps=#{@steps.count}>"
end

#matches?(context) ⇒ Boolean

Checks if this branch’s condition matches the given context

Parameters:

Returns:

  • (Boolean)

    true if condition matches or is nil (default branch)



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/better_service/workflows/branch.rb', line 40

def matches?(context)
  return true if condition.nil? # Default branch always matches

  if condition.is_a?(Proc)
    context.instance_exec(context, &condition)
  else
    condition.call(context)
  end
rescue StandardError => e
  Rails.logger.error "Branch condition evaluation failed: #{e.message}"
  false
end