DEV Community

loading...

Playing with execution flows in Ruby

olistik profile image olistik ・1 min read

Let's define a simple Result class:

class Result
  def initialize(success: true, data: nil); @success = success; @data = data; end
  def success?; @success == true; end
  def error?; !success?; end
  def data; @data; end
  def self.success(data = nil); new(data: data); end
  def self.error(data = nil); new(success: false, data: data); end
end
Enter fullscreen mode Exit fullscreen mode

and then a Flow class:

class Flow
  attr_accessor :tasks, :result

  def initialize(tasks: [])
    self.tasks = tasks
    self.result = nil
  end

  def step(task)
    self.tasks << task
  end

  def call
    tasks.each do |task|
      begin
        self.data = task.call
        self.result = Result.success(data) unless result.kind_of?(Result)
      rescue => exception
        self.result = Result.error(exception)
      end
      return result if result.error?
    end

    result
  end
end
Enter fullscreen mode Exit fullscreen mode

We can now do some interesting things such as:

flow = Flow.new
flow.step -> { puts '#1' }
flow.step -> { puts '#2'; 3 * 3 }
flow.step -> { puts '#3 (error)'; raise 'foo' }
flow.step -> { puts '#4' }
result = flow.call

result.error? # => true
result.data # => #<RuntimeError: foo>
Enter fullscreen mode Exit fullscreen mode

Discussion (0)

Forem Open with the Forem app