Class: SafetyDance

Inherits:
Object
  • Object
show all
Defined in:
lib/safety_dance.rb,
lib/safety_dance/version.rb

Overview

Generic ‘Result’ object for declarative result success/failure/cascade handling.

Usage:

def some_action_that_succeeds(msg); msg; end
def some_action_that_fails(msg); raise msg; end

SafetyDance.new { some_action_that_succeeds(:success) } #=> SafetyDance

SafetyDance.new { some_action_that_succeeds(:success) }
  .value {|error| "action failed with error #{error}" } #=> :success

SafetyDance.new { some_action_that_fails("fail")}
  .value {|error| "action failed with error #{error}" } #=> "action failed with error 'RuntimeError fail'"

SafetyDance.new { some_action_that_succeeds(:success) }
  .then { some_action_that_succeeds(:another_success }
  .value {|error| "I am handling #{error}" } # => :another_success

SafetyDance.new { some_action_that_fails("fail1") }
  .then { some_action_that_fails("fail2") }
  .then { some_action_that_succeeds(:another_success }
  .then { some_action_that_fails("fail3") }
  .value {|error| "I am handling #{error}" } # I am handling 'RuntimeError fail1'"

Result object pattern is from johnnunemaker.com/resilience-in-ruby/ e.g. github.com/github/github-ds/blob/fbda5389711edfb4c10b6c6bad19311dfcb1bac1/lib/github/result.rb

Constant Summary collapse

VERSION =
"1.0.0"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSafetyDance

Returns a new instance of SafetyDance.



31
32
33
34
35
36
# File 'lib/safety_dance.rb', line 31

def initialize
	@value = yield
	@error = nil
rescue => e
	@error = e
end

Class Method Details

.error(e) ⇒ Object



97
98
99
100
101
# File 'lib/safety_dance.rb', line 97

def self.error(e)
  result = allocate
  result.instance_variable_set(:@error, e)
  result
end

Instance Method Details

#errorObject



52
53
54
# File 'lib/safety_dance.rb', line 52

def error
  @error
end

#ok?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/safety_dance.rb', line 38

def ok?
  @error.nil?
end

#rescueObject



87
88
89
90
91
92
93
94
95
# File 'lib/safety_dance.rb', line 87

def rescue
  return self if ok?
  result = SafetyDance.new { yield(@error) }
  if result.ok? && result.value! == @error
    self
  else
    result
  end
end

#thenObject



75
76
77
78
# File 'lib/safety_dance.rb', line 75

def then
  return self if !ok?
  SafetyDance.new { yield(@value) }
end

#then_tapObject



80
81
82
83
84
85
# File 'lib/safety_dance.rb', line 80

def then_tap
  self.then do |value|
    yield value
    value
  end
end

#to_sObject Also known as: inspect



42
43
44
45
46
47
48
# File 'lib/safety_dance.rb', line 42

def to_s
  if ok?
    "#<SafetyDance:0x%x value: %s>" % [object_id, @value.inspect]
  else
    "#<SafetyDance:0x%x error: %s>" % [object_id, @error.inspect]
  end
end

#valueObject



56
57
58
59
60
61
62
63
64
65
# File 'lib/safety_dance.rb', line 56

def value
  unless block_given?
    fail ArgumentError, "must provide a block to SafetyDance#value to be invoked in case of error"
  end
  if ok?
    @value
  else
    yield @error
  end
end

#value!Object



67
68
69
70
71
72
73
# File 'lib/safety_dance.rb', line 67

def value!
  if ok?
    @value
  else
    raise @error
  end
end