cuprum 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +85 -9
- data/DEVELOPMENT.md +58 -42
- data/README.md +414 -754
- data/lib/cuprum.rb +1 -25
- data/lib/cuprum/built_in/identity_command.rb +4 -4
- data/lib/cuprum/chaining.rb +139 -148
- data/lib/cuprum/command.rb +24 -15
- data/lib/cuprum/command_factory.rb +43 -19
- data/lib/cuprum/currying.rb +78 -0
- data/lib/cuprum/currying/curried_command.rb +109 -0
- data/lib/cuprum/error.rb +37 -0
- data/lib/cuprum/errors/command_not_implemented.rb +35 -0
- data/lib/cuprum/errors/operation_not_called.rb +35 -0
- data/lib/cuprum/operation.rb +37 -28
- data/lib/cuprum/processing.rb +45 -82
- data/lib/cuprum/result.rb +52 -127
- data/lib/cuprum/result_helpers.rb +14 -105
- data/lib/cuprum/rspec.rb +8 -0
- data/lib/cuprum/rspec/be_a_result.rb +19 -0
- data/lib/cuprum/rspec/be_a_result_matcher.rb +286 -0
- data/lib/cuprum/steps.rb +275 -0
- data/lib/cuprum/utils/instance_spy.rb +9 -2
- data/lib/cuprum/version.rb +1 -1
- metadata +14 -8
- data/lib/cuprum/errors/process_not_implemented_error.rb +0 -14
- data/lib/cuprum/utils/result_not_empty_warning.rb +0 -72
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/error'
|
4
|
+
require 'cuprum/errors'
|
5
|
+
|
6
|
+
module Cuprum::Errors
|
7
|
+
# Error class to be used when trying to access the result of an uncalled
|
8
|
+
# Operation.
|
9
|
+
class OperationNotCalled < Cuprum::Error
|
10
|
+
COMPARABLE_PROPERTIES = %i[operation].freeze
|
11
|
+
private_constant :COMPARABLE_PROPERTIES
|
12
|
+
|
13
|
+
# Format for generating error message.
|
14
|
+
MESSAGE_FORMAT = '%s was not called and does not have a result'
|
15
|
+
|
16
|
+
# @param operation [Cuprum::Operation] The uncalled operation.
|
17
|
+
def initialize(operation:)
|
18
|
+
@operation = operation
|
19
|
+
|
20
|
+
class_name = operation&.class&.name || 'operation'
|
21
|
+
message = MESSAGE_FORMAT % class_name
|
22
|
+
|
23
|
+
super(message: message)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Cuprum::Operation] The uncalled operation.
|
27
|
+
attr_reader :operation
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def comparable_properties
|
32
|
+
COMPARABLE_PROPERTIES
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/cuprum/operation.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'cuprum/command'
|
2
|
+
require 'cuprum/errors/operation_not_called'
|
2
3
|
|
3
4
|
module Cuprum
|
4
5
|
# Functional object with syntactic sugar for tracking the last result.
|
@@ -45,7 +46,6 @@ module Cuprum
|
|
45
46
|
# @return [Cuprum::Result] The result from the most recent call of the
|
46
47
|
# operation.
|
47
48
|
attr_reader :result
|
48
|
-
alias_method :to_result, :result
|
49
49
|
|
50
50
|
# @overload call(*arguments, **keywords, &block)
|
51
51
|
# Executes the logic encoded in the constructor block, or the #process
|
@@ -61,12 +61,8 @@ module Cuprum
|
|
61
61
|
# @yield If a block argument is given, it will be passed to the
|
62
62
|
# implementation.
|
63
63
|
#
|
64
|
-
# @raise [Cuprum::Errors::ProcessNotImplementedError] Unless a block was
|
65
|
-
# passed to the constructor or the #process method was overriden by a
|
66
|
-
# Command subclass.
|
67
|
-
#
|
68
64
|
# @see Cuprum::Command#call
|
69
|
-
def call *args, &block
|
65
|
+
def call *args, **kwargs, &block
|
70
66
|
reset! if called? # Clear reference to most recent result.
|
71
67
|
|
72
68
|
@result = super
|
@@ -80,23 +76,18 @@ module Cuprum
|
|
80
76
|
!result.nil?
|
81
77
|
end # method called?
|
82
78
|
|
83
|
-
# @return [
|
84
|
-
# operation has not been called.
|
85
|
-
def
|
86
|
-
called? ? result.
|
87
|
-
end # method
|
79
|
+
# @return [Object] the error (if any) from the most recent result, or nil
|
80
|
+
# if the operation has not been called.
|
81
|
+
def error
|
82
|
+
called? ? result.error : nil
|
83
|
+
end # method error
|
88
84
|
|
89
|
-
# @return [Boolean] true if the most recent result had
|
90
|
-
# the most recent result had no
|
91
|
-
# called.
|
85
|
+
# @return [Boolean] true if the most recent result had an error, or false
|
86
|
+
# if the most recent result had no error or if the operation has not
|
87
|
+
# been called.
|
92
88
|
def failure?
|
93
89
|
called? ? result.failure? : false
|
94
|
-
end # method
|
95
|
-
|
96
|
-
# @return [Boolean] true if the most recent was halted, otherwise false.
|
97
|
-
def halted?
|
98
|
-
called? ? result.halted? : false
|
99
|
-
end # method halted?
|
90
|
+
end # method failure?
|
100
91
|
|
101
92
|
# Clears the reference to the most recent call of the operation, if any.
|
102
93
|
# This allows the result and any referenced data to be garbage collected.
|
@@ -110,13 +101,31 @@ module Cuprum
|
|
110
101
|
@result = nil
|
111
102
|
end # method reset
|
112
103
|
|
113
|
-
# @return [
|
114
|
-
#
|
115
|
-
|
104
|
+
# @return [Symbol, nil] the status of the most recent result, or nil if
|
105
|
+
# the operation has not been called.
|
106
|
+
def status
|
107
|
+
called? ? result.status : nil
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Boolean] true if the most recent result had no error, or false
|
111
|
+
# if the most recent result had an error or if the operation has not
|
112
|
+
# been called.
|
116
113
|
def success?
|
117
114
|
called? ? result.success? : false
|
118
115
|
end # method success?
|
119
116
|
|
117
|
+
# Returns the most result if the operation was previously called.
|
118
|
+
# Otherwise, returns a failing result.
|
119
|
+
#
|
120
|
+
# @return [Cuprum::Result] the most recent result or failing result.
|
121
|
+
def to_cuprum_result
|
122
|
+
return result if result
|
123
|
+
|
124
|
+
error = Cuprum::Errors::OperationNotCalled.new(operation: self)
|
125
|
+
|
126
|
+
Cuprum::Result.new(error: error)
|
127
|
+
end
|
128
|
+
|
120
129
|
# @return [Object] the value of the most recent result, or nil if the
|
121
130
|
# operation has not been called.
|
122
131
|
def value
|
@@ -131,15 +140,12 @@ module Cuprum
|
|
131
140
|
# @!method called?
|
132
141
|
# (see Cuprum::Operation::Mixin#called?)
|
133
142
|
|
134
|
-
# @!method
|
135
|
-
# (see Cuprum::Operation::Mixin#
|
143
|
+
# @!method error
|
144
|
+
# (see Cuprum::Operation::Mixin#error)
|
136
145
|
|
137
146
|
# @!method failure?
|
138
147
|
# (see Cuprum::Operation::Mixin#failure?)
|
139
148
|
|
140
|
-
# @!method halted?
|
141
|
-
# (see Cuprum::Operation::Mixin#halted?)
|
142
|
-
|
143
149
|
# @!method reset!
|
144
150
|
# (see Cuprum::Operation::Mixin#reset!)
|
145
151
|
|
@@ -149,6 +155,9 @@ module Cuprum
|
|
149
155
|
# @!method success?
|
150
156
|
# (see Cuprum::Operation::Mixin#success?)
|
151
157
|
|
158
|
+
# @!method to_cuprum_result
|
159
|
+
# (see Cuprum::Operation::Mixin#to_cuprum_result?)
|
160
|
+
|
152
161
|
# @!method value
|
153
162
|
# (see Cuprum::Operation::Mixin#value)
|
154
163
|
end # class
|
data/lib/cuprum/processing.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/errors/command_not_implemented'
|
4
|
+
require 'cuprum/result_helpers'
|
3
5
|
|
4
6
|
module Cuprum
|
5
7
|
# Functional implementation for creating a command object. Cuprum::Processing
|
@@ -12,14 +14,14 @@ module Cuprum
|
|
12
14
|
#
|
13
15
|
# def initialize addend
|
14
16
|
# @addend = addend
|
15
|
-
# end
|
17
|
+
# end
|
16
18
|
#
|
17
19
|
# private
|
18
20
|
#
|
19
21
|
# def process int
|
20
22
|
# int + addend
|
21
|
-
# end
|
22
|
-
# end
|
23
|
+
# end
|
24
|
+
# end
|
23
25
|
#
|
24
26
|
# adder = AdderCommand.new(2)
|
25
27
|
# result = adder.call(3)
|
@@ -35,31 +37,28 @@ module Cuprum
|
|
35
37
|
#
|
36
38
|
# def process value
|
37
39
|
# if value.negative?
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# return nil
|
41
|
-
# end # if
|
40
|
+
# return Cuprum::Result.new(error: 'value cannot be negative')
|
41
|
+
# end
|
42
42
|
#
|
43
43
|
# Math.sqrt(value)
|
44
|
-
# end
|
45
|
-
# end
|
44
|
+
# end
|
45
|
+
# end
|
46
46
|
#
|
47
47
|
# result = SquareRootCommand.new.call(2)
|
48
48
|
# result.value #=> 1.414
|
49
49
|
# result.success? #=> true
|
50
50
|
# result.failure? #=> false
|
51
|
-
# result.
|
51
|
+
# result.error #=> nil
|
52
52
|
#
|
53
53
|
# result = SquareRootCommand.new.call(-1)
|
54
54
|
# result.value #=> nil
|
55
55
|
# result.success? #=> false
|
56
56
|
# result.failure? #=> true
|
57
|
-
# result.
|
57
|
+
# result.error #=> 'value cannot be negative'
|
58
58
|
#
|
59
59
|
# @see Cuprum::Command
|
60
60
|
module Processing
|
61
|
-
|
62
|
-
private_constant :VALUE_METHODS
|
61
|
+
include Cuprum::ResultHelpers
|
63
62
|
|
64
63
|
# Returns a nonnegative integer for commands that take a fixed number of
|
65
64
|
# arguments. For commands that take a variable number of arguments, returns
|
@@ -68,7 +67,7 @@ module Cuprum
|
|
68
67
|
# @return [Integer] The number of arguments.
|
69
68
|
def arity
|
70
69
|
method(:process).arity
|
71
|
-
end
|
70
|
+
end
|
72
71
|
|
73
72
|
# @overload call(*arguments, **keywords, &block)
|
74
73
|
# Executes the command implementation and returns a Cuprum::Result or
|
@@ -76,14 +75,12 @@ module Cuprum
|
|
76
75
|
#
|
77
76
|
# Each time #call is invoked, the object performs the following steps:
|
78
77
|
#
|
79
|
-
# 1.
|
80
|
-
#
|
81
|
-
# 2.
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# Otherwise, the return value of #process is assigned to the #value
|
86
|
-
# property of the result, and the result is returned by #call.
|
78
|
+
# 1. The #process method is called, passing the arguments, keywords, and
|
79
|
+
# block that were passed to #call.
|
80
|
+
# 2. If the value returned by #process is a Cuprum::Result or compatible
|
81
|
+
# object, that result is directly returned by #call.
|
82
|
+
# 3. Otherwise, the value returned by #process will be wrapped in a
|
83
|
+
# successful result, which will be returned by #call.
|
87
84
|
#
|
88
85
|
# @param arguments [Array] Arguments to be passed to the implementation.
|
89
86
|
#
|
@@ -93,43 +90,28 @@ module Cuprum
|
|
93
90
|
#
|
94
91
|
# @yield If a block argument is given, it will be passed to the
|
95
92
|
# implementation.
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
private
|
104
|
-
|
105
|
-
# @return [Cuprum::Result] The current result. Only available while #process
|
106
|
-
# is being called.
|
107
|
-
attr_reader :result
|
108
|
-
|
109
|
-
def build_result value = nil, **options
|
110
|
-
Cuprum::Result.new(value, options)
|
111
|
-
end # method build_result
|
93
|
+
def call(*args, **kwargs, &block)
|
94
|
+
value =
|
95
|
+
if kwargs.empty?
|
96
|
+
process(*args, &block)
|
97
|
+
else
|
98
|
+
process(*args, **kwargs, &block)
|
99
|
+
end
|
112
100
|
|
113
|
-
|
114
|
-
if value_is_result?(other)
|
115
|
-
return result if result == other
|
101
|
+
return value.to_cuprum_result if value_is_result?(value)
|
116
102
|
|
117
|
-
|
103
|
+
build_result(value: value)
|
104
|
+
end
|
118
105
|
|
119
|
-
|
120
|
-
else
|
121
|
-
result.value = other
|
122
|
-
|
123
|
-
result
|
124
|
-
end # if-else
|
125
|
-
end # method merge_results
|
106
|
+
private
|
126
107
|
|
127
108
|
# @!visibility public
|
128
109
|
# @overload process(*arguments, **keywords, &block)
|
129
110
|
# The implementation of the command, to be executed when the #call method
|
130
|
-
# is called.
|
131
|
-
#
|
132
|
-
#
|
111
|
+
# is called. If #process returns a result, that result will be returned by
|
112
|
+
# #call; otherwise, the value returned by #process will be wrapped in a
|
113
|
+
# successful Cuprum::Result object. This method should not be called
|
114
|
+
# directly.
|
133
115
|
#
|
134
116
|
# @param arguments [Array] The arguments, if any, passed from #call.
|
135
117
|
#
|
@@ -139,34 +121,15 @@ module Cuprum
|
|
139
121
|
#
|
140
122
|
# @return [Object] the value of the result object to be returned by #call.
|
141
123
|
#
|
142
|
-
# @raise [Cuprum::Errors::ProcessNotImplementedError] Unless a block was
|
143
|
-
# passed to the constructor or the #process method was overriden by a
|
144
|
-
# Command subclass.
|
145
|
-
#
|
146
124
|
# @note This is a private method.
|
147
|
-
def process
|
148
|
-
|
149
|
-
end # method process
|
150
|
-
|
151
|
-
def process_with_result result, *args, &block
|
152
|
-
@result = result
|
153
|
-
value = process(*args, &block)
|
154
|
-
|
155
|
-
merge_results(result, value)
|
156
|
-
ensure
|
157
|
-
@result = nil
|
158
|
-
end # method process_with_result
|
159
|
-
|
160
|
-
def value_is_result? value
|
161
|
-
VALUE_METHODS.all? { |method_name| value.respond_to?(method_name) }
|
162
|
-
end # method value
|
163
|
-
|
164
|
-
def warn_unless_empty! result
|
165
|
-
return unless result.respond_to?(:empty?) && !result.empty?
|
125
|
+
def process(*_args)
|
126
|
+
error = Cuprum::Errors::CommandNotImplemented.new(command: self)
|
166
127
|
|
167
|
-
|
128
|
+
build_result(error: error)
|
129
|
+
end
|
168
130
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
131
|
+
def value_is_result?(value)
|
132
|
+
value.respond_to?(:to_cuprum_result)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/cuprum/result.rb
CHANGED
@@ -1,166 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cuprum'
|
2
4
|
|
3
5
|
module Cuprum
|
4
6
|
# Data object that encapsulates the result of calling a Cuprum command.
|
5
7
|
class Result
|
8
|
+
STATUSES = %i[success failure].freeze
|
9
|
+
|
6
10
|
# @param value [Object] The value returned by calling the command.
|
7
|
-
# @param
|
8
|
-
# called.
|
9
|
-
|
11
|
+
# @param error [Object] The error (if any) generated when the command was
|
12
|
+
# called. Can be a Cuprum::Error, a model errors object, etc.
|
13
|
+
# @param status [String, Symbol] The status of the result. Must be :success,
|
14
|
+
# :failure, or nil.
|
15
|
+
def initialize(value: nil, error: nil, status: nil)
|
10
16
|
@value = value
|
11
|
-
@
|
12
|
-
@status =
|
13
|
-
|
14
|
-
end # constructor
|
17
|
+
@error = error
|
18
|
+
@status = resolve_status(status)
|
19
|
+
end
|
15
20
|
|
16
21
|
# @return [Object] the value returned by calling the command.
|
17
|
-
|
22
|
+
attr_reader :value
|
18
23
|
|
19
|
-
# @return [
|
24
|
+
# @return [Object] the error (if any) generated when the command was
|
20
25
|
# called.
|
21
|
-
|
26
|
+
attr_reader :error
|
27
|
+
|
28
|
+
# @return [Symbol] the status of the result, either :success or :failure.
|
29
|
+
attr_reader :status
|
22
30
|
|
23
|
-
# rubocop:disable Metrics/AbcSize
|
24
31
|
# rubocop:disable Metrics/CyclomaticComplexity
|
25
|
-
# rubocop:disable Metrics/MethodLength
|
26
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
27
32
|
|
28
33
|
# Compares the other object to the result.
|
29
34
|
#
|
30
35
|
# @param other [#value, #success?] An object responding to, at minimum,
|
31
|
-
# #value and #success?. If present, the #failure
|
32
|
-
#
|
36
|
+
# #value and #success?. If present, the #failure? and #error values
|
37
|
+
# will also be compared.
|
33
38
|
#
|
34
39
|
# @return [Boolean] True if all present values match the result, otherwise
|
35
40
|
# false.
|
36
|
-
def ==
|
37
|
-
return false unless other.respond_to?(:value)
|
38
|
-
|
39
|
-
unless other.respond_to?(:
|
40
|
-
return false
|
41
|
-
end # unless
|
42
|
-
|
43
|
-
if other.respond_to?(:failure?) && other.failure? != failure?
|
44
|
-
return false
|
45
|
-
end # if
|
46
|
-
|
47
|
-
if other.respond_to?(:errors) && other.errors != errors
|
48
|
-
return false
|
49
|
-
end # if
|
50
|
-
|
51
|
-
if other.respond_to?(:halted?) && other.halted? != halted?
|
52
|
-
return false
|
53
|
-
end # if
|
41
|
+
def ==(other)
|
42
|
+
return false unless other.respond_to?(:value) && other.value == value
|
43
|
+
return false unless other.respond_to?(:status) && other.status == status
|
44
|
+
return false unless other.respond_to?(:error) && other.error == error
|
54
45
|
|
55
46
|
true
|
56
|
-
end
|
57
|
-
# rubocop:enable Metrics/AbcSize
|
47
|
+
end
|
58
48
|
# rubocop:enable Metrics/CyclomaticComplexity
|
59
|
-
# rubocop:enable Metrics/MethodLength
|
60
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
61
|
-
|
62
|
-
# @return [Boolean] true if the result is empty, i.e. has no value or errors
|
63
|
-
# and does not have its status set or is halted.
|
64
|
-
def empty?
|
65
|
-
value.nil? && errors.empty? && @status.nil? && !halted?
|
66
|
-
end # method empty?
|
67
49
|
|
68
|
-
#
|
69
|
-
# errors.
|
70
|
-
#
|
71
|
-
# @return [Cuprum::Result] The result.
|
72
|
-
def failure!
|
73
|
-
@status = :failure
|
74
|
-
|
75
|
-
self
|
76
|
-
end # method failure!
|
77
|
-
|
78
|
-
# @return [Boolean] false if the command did not generate any errors,
|
79
|
-
# otherwise true.
|
50
|
+
# @return [Boolean] true if the result status is :failure, otherwise false.
|
80
51
|
def failure?
|
81
|
-
@status == :failure
|
82
|
-
end
|
52
|
+
@status == :failure
|
53
|
+
end
|
83
54
|
|
84
|
-
#
|
85
|
-
# run.
|
86
|
-
#
|
87
|
-
# @return [Cuprum::Result] The result.
|
88
|
-
def halt!
|
89
|
-
@halted = true
|
90
|
-
|
91
|
-
self
|
92
|
-
end # method halt!
|
93
|
-
|
94
|
-
# @return [Boolean] true if the command has been halted, and will not run
|
95
|
-
# any subsequent chained commands.
|
96
|
-
def halted?
|
97
|
-
@halted
|
98
|
-
end # method halted?
|
99
|
-
|
100
|
-
# Marks the result as a success, whether or not the command generated any
|
101
|
-
# errors.
|
102
|
-
#
|
103
|
-
# @return [Cuprum::Result] The result.
|
104
|
-
def success!
|
105
|
-
@status = :success
|
106
|
-
|
107
|
-
self
|
108
|
-
end # method success!
|
109
|
-
|
110
|
-
# @return [Boolean] true if the command did not generate any errors,
|
111
|
-
# otherwise false.
|
55
|
+
# @return [Boolean] true if the result status is :success, otherwise false.
|
112
56
|
def success?
|
113
|
-
@status == :success
|
114
|
-
end
|
57
|
+
@status == :success
|
58
|
+
end
|
115
59
|
|
116
60
|
# @return [Cuprum::Result] The result.
|
117
|
-
def
|
61
|
+
def to_cuprum_result
|
118
62
|
self
|
119
|
-
end
|
120
|
-
|
121
|
-
# @api private
|
122
|
-
def update other_result
|
123
|
-
return self if other_result.nil?
|
124
|
-
|
125
|
-
self.value = other_result.value
|
63
|
+
end
|
126
64
|
|
127
|
-
|
128
|
-
|
129
|
-
update_errors(other_result)
|
65
|
+
private
|
130
66
|
|
131
|
-
|
67
|
+
def defined_statuses
|
68
|
+
self.class::STATUSES
|
69
|
+
end
|
132
70
|
|
133
|
-
|
134
|
-
|
71
|
+
def normalize_status(status)
|
72
|
+
return status unless status.is_a?(String) || status.is_a?(Symbol)
|
135
73
|
|
136
|
-
|
137
|
-
|
138
|
-
attr_reader :status
|
74
|
+
tools.string_tools.underscore(status).intern
|
75
|
+
end
|
139
76
|
|
140
|
-
|
141
|
-
|
142
|
-
# @!visibility public
|
143
|
-
#
|
144
|
-
# Generates an empty errors object. When the command is called, the result
|
145
|
-
# will have its #errors property initialized to the value returned by
|
146
|
-
# #build_errors. By default, this is an array. If you want to use a custom
|
147
|
-
# errors object type, override this method in a subclass.
|
148
|
-
#
|
149
|
-
# @return [Array] An empty errors object.
|
150
|
-
def build_errors
|
151
|
-
[]
|
152
|
-
end # method build_errors
|
77
|
+
def resolve_status(status)
|
78
|
+
return error.nil? ? :success : :failure if status.nil?
|
153
79
|
|
154
|
-
|
155
|
-
return if other_result.errors.empty?
|
80
|
+
normalized = normalize_status(status)
|
156
81
|
|
157
|
-
|
158
|
-
end # method update_errors
|
82
|
+
return normalized if defined_statuses.include?(normalized)
|
159
83
|
|
160
|
-
|
161
|
-
|
84
|
+
raise ArgumentError, "invalid status #{status.inspect}"
|
85
|
+
end
|
162
86
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
87
|
+
def tools
|
88
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|