result_vault 1.2.3
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 +7 -0
- data/lib/result_vault/version.rb +5 -0
- data/lib/result_vault.rb +352 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cc62221bda4ff92f32af12135f1e99b44a85c0960494b3daad9d727dbc7f78f0
|
4
|
+
data.tar.gz: c2d5f53c3919a4eca97a89e1c11d1e89167eff80b5de6d5f94595d9e7d398b4c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a6028e1dbc8910a763ddc914f2261280d1d8371747ff480e028774048735620bdf695be5bd9d2c0067582c421b739a96e80d7332a5a4bc250b3ddb669a55ba1
|
7
|
+
data.tar.gz: dea5c853880da64aca0e40924960c7787b77c68f80c718a6f0f7875e50b574c3422cd526f2828ff5f038919d2632d674ed17bcaee0f368a0a7caecf2aa2ca7d0
|
data/lib/result_vault.rb
ADDED
@@ -0,0 +1,352 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "result_vault/version"
|
4
|
+
|
5
|
+
##
|
6
|
+
# A mechanism for returning a multi-factor result from any object call.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# result = ResultVault.new(error_message: "missing user", user_id: 123)
|
10
|
+
# result.user_name = 'Test User'
|
11
|
+
#
|
12
|
+
# result.user_id #=> 123
|
13
|
+
# result.user_name #=> 'Test User'
|
14
|
+
# result.error_message #=> "missing user"
|
15
|
+
#
|
16
|
+
class ResultVault
|
17
|
+
|
18
|
+
# ======================================================================
|
19
|
+
# = Public Methods
|
20
|
+
# ======================================================================
|
21
|
+
|
22
|
+
##
|
23
|
+
# Returns the success value
|
24
|
+
#
|
25
|
+
# @return [boolean] success
|
26
|
+
#
|
27
|
+
def success?
|
28
|
+
!!@success
|
29
|
+
end
|
30
|
+
alias :ok? :success?
|
31
|
+
alias :good? :success?
|
32
|
+
alias :pass? :success?
|
33
|
+
alias :passed? :success?
|
34
|
+
alias :succeeded? :success?
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
# Set success to true
|
39
|
+
#
|
40
|
+
def success=(val)
|
41
|
+
_update_vault(:success, val)
|
42
|
+
end
|
43
|
+
alias :ok= :success=
|
44
|
+
alias :good= :success=
|
45
|
+
alias :pass= :success=
|
46
|
+
alias :passed= :success=
|
47
|
+
alias :succeeded= :success=
|
48
|
+
|
49
|
+
|
50
|
+
##
|
51
|
+
# Resturns the status or nil
|
52
|
+
#
|
53
|
+
# @return [Symbol, String, *, nil]
|
54
|
+
#
|
55
|
+
def status
|
56
|
+
@status
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
##
|
61
|
+
# Sets the status
|
62
|
+
#
|
63
|
+
# @param [*] new_status
|
64
|
+
# a description of the error
|
65
|
+
#
|
66
|
+
def status=(new_status)
|
67
|
+
_update_vault(:status, new_status)
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
##
|
72
|
+
# Returns the stored exception
|
73
|
+
#
|
74
|
+
# @returns [Exception, nil]
|
75
|
+
#
|
76
|
+
def exception
|
77
|
+
@exception
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
##
|
82
|
+
# Sets the stored exception
|
83
|
+
#
|
84
|
+
# @param [Exception] xcptn
|
85
|
+
# an instance of the Exception class
|
86
|
+
#
|
87
|
+
def exception=(xcptn)
|
88
|
+
_update_vault(:exception, xcptn)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
##
|
93
|
+
# Resturns the stored error message or an empty string
|
94
|
+
#
|
95
|
+
# @return [String]
|
96
|
+
#
|
97
|
+
def error_message
|
98
|
+
@error_message
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
##
|
103
|
+
# Sets the error message
|
104
|
+
#
|
105
|
+
# @param [String] err_msg
|
106
|
+
# a description of the error
|
107
|
+
#
|
108
|
+
def error_message=(err_msg)
|
109
|
+
_update_vault(:error_message, err_msg)
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
##
|
114
|
+
# Raise an exception if the user is setting data directly
|
115
|
+
#
|
116
|
+
def data=(*)
|
117
|
+
fail ArgumentError, ":data is a reserved keyword and may not be set directly."
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
##
|
122
|
+
# Return a frozen copy of the stoted data
|
123
|
+
#
|
124
|
+
# @returns [Hash]
|
125
|
+
#
|
126
|
+
def data
|
127
|
+
result = @data.dup
|
128
|
+
result[:success] = success?
|
129
|
+
result[:status] = status
|
130
|
+
result[:error_message] = error_message
|
131
|
+
result.freeze
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
##
|
136
|
+
# Return an array of method names
|
137
|
+
#
|
138
|
+
# @retun [Array[Symbol]]
|
139
|
+
#
|
140
|
+
def methods(regular = true)
|
141
|
+
method_names = super(regular)
|
142
|
+
method_names += _data_method_names
|
143
|
+
method_names -= _excluded_method_names
|
144
|
+
|
145
|
+
return method_names
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
##
|
150
|
+
# Returns true if the vaul responds to the given methods
|
151
|
+
#
|
152
|
+
# @param [Symbol, String]
|
153
|
+
def respond_to?(name)
|
154
|
+
return false if _excluded_method_names.include?(name.to_sym)
|
155
|
+
return true if _data_method_names.include?(name.to_sym)
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
# ======================================================================
|
161
|
+
# = Private
|
162
|
+
# ======================================================================
|
163
|
+
#
|
164
|
+
private
|
165
|
+
|
166
|
+
##
|
167
|
+
# Initialize the response object's data-hash with the given arguments
|
168
|
+
#
|
169
|
+
# @param [Hash] args
|
170
|
+
# a list of keyword parameters
|
171
|
+
#
|
172
|
+
def initialize(**args)
|
173
|
+
@data = {}
|
174
|
+
@success = false
|
175
|
+
@exception = nil
|
176
|
+
@error_message = ''
|
177
|
+
|
178
|
+
# add all arguments to the data hash
|
179
|
+
args.each { |key, val| _update_vault(key, val) }
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
##
|
184
|
+
# Update the Vault's data
|
185
|
+
#
|
186
|
+
# @param [Symbol] key
|
187
|
+
# the key to use for storage
|
188
|
+
#
|
189
|
+
# @param [*]
|
190
|
+
# the value to be stored
|
191
|
+
#
|
192
|
+
def _update_vault(key, val)
|
193
|
+
_assert_symbolic_key(key)
|
194
|
+
_assert_not_frozen!
|
195
|
+
|
196
|
+
case key
|
197
|
+
when :data
|
198
|
+
fail ArgumentError, ":data is a reserved keyword and may not be set directly."
|
199
|
+
|
200
|
+
when :status
|
201
|
+
@status = val
|
202
|
+
|
203
|
+
when :exception
|
204
|
+
_assert_valid_exception(val)
|
205
|
+
@exception = val
|
206
|
+
|
207
|
+
when :success, :ok, :good, :pass, :passed, :succeeded
|
208
|
+
@success = !!val
|
209
|
+
|
210
|
+
when :error_message
|
211
|
+
@error_message = val
|
212
|
+
|
213
|
+
else
|
214
|
+
@data[key] = val
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
##
|
220
|
+
# Return an array of the method names that should be excluded
|
221
|
+
# from the list of available methods.
|
222
|
+
#
|
223
|
+
# @note
|
224
|
+
# This changes on whether the vault is frozen or not
|
225
|
+
#
|
226
|
+
def _excluded_method_names
|
227
|
+
excluded = [:data=]
|
228
|
+
|
229
|
+
if frozen?
|
230
|
+
excluded += [:success=, :ok=, :good=, :pass=, :succeeded=, :status=, :exception=, :error_messgae=]
|
231
|
+
|
232
|
+
@data.keys.each { |key| excluded << "#{key}=".to_sym }
|
233
|
+
end
|
234
|
+
|
235
|
+
return excluded
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
##
|
240
|
+
# Return an array of the data keys for this vault,
|
241
|
+
# omitting the setter methods if the vault is frozen
|
242
|
+
#
|
243
|
+
def _data_method_names
|
244
|
+
data_methods = []
|
245
|
+
|
246
|
+
@data.keys.each do |key|
|
247
|
+
data_methods << key
|
248
|
+
data_methods << "#{key}=".to_sym unless frozen?
|
249
|
+
end
|
250
|
+
|
251
|
+
return data_methods
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
##
|
256
|
+
# Test if an ancestor class has the method, otherwise test if
|
257
|
+
# it's a vault dynamic method
|
258
|
+
#
|
259
|
+
# @param [Symbol] method_sym
|
260
|
+
# the name of the method
|
261
|
+
#
|
262
|
+
# @param [Array] arguments
|
263
|
+
# the arguments for the method
|
264
|
+
#
|
265
|
+
# @block
|
266
|
+
# an optional block
|
267
|
+
#
|
268
|
+
def method_missing(method_sym, *arguments, &block)
|
269
|
+
no_method_error = nil
|
270
|
+
catch :check_ancestors do
|
271
|
+
super
|
272
|
+
rescue => e
|
273
|
+
no_method_error = e
|
274
|
+
throw :check_ancestors
|
275
|
+
end
|
276
|
+
|
277
|
+
_dynamic_method_missing(method_sym, arguments.first, no_method_error)
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
##
|
282
|
+
# If the missing method name ends in an '=' character, update the data.
|
283
|
+
# If the missing method name is already within the data hash, return the value
|
284
|
+
#
|
285
|
+
# @param [Symbol] method_sym
|
286
|
+
# the name of the method
|
287
|
+
#
|
288
|
+
# @param * the value to set
|
289
|
+
# the value for setting the method
|
290
|
+
#
|
291
|
+
# @param [NoMethodError]
|
292
|
+
# the no methed exection to raise if there's no dynamic method
|
293
|
+
#
|
294
|
+
def _dynamic_method_missing(method_sym, val, no_method_error)
|
295
|
+
case
|
296
|
+
when @data.keys.include?(method_sym)
|
297
|
+
@data[method_sym]
|
298
|
+
|
299
|
+
when method_sym[-1].eql?('=')
|
300
|
+
_update_vault(method_sym[0..-2].to_sym, val)
|
301
|
+
|
302
|
+
else
|
303
|
+
raise no_method_error
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
|
308
|
+
##
|
309
|
+
# @return [boolean]
|
310
|
+
# true if the given method end with an '=' or the method exists
|
311
|
+
#
|
312
|
+
def respond_to_missing?(method_sym, include_private = false)
|
313
|
+
return true if super
|
314
|
+
return true if @data.keys.include?(method_sym)
|
315
|
+
return false if frozen?
|
316
|
+
|
317
|
+
method_sym[-1].eql?('=')
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
# = Assertions
|
322
|
+
# ======================================================================
|
323
|
+
|
324
|
+
##
|
325
|
+
# Raise an exception if the provided key is not a Symbol
|
326
|
+
#
|
327
|
+
def _assert_symbolic_key(key)
|
328
|
+
return if key.is_a?(Symbol)
|
329
|
+
fail ArgumentError, "String key submitted: '#{key}'. Keys should be Symbols only."
|
330
|
+
end
|
331
|
+
|
332
|
+
|
333
|
+
##
|
334
|
+
# Raise an error if the result is forzen
|
335
|
+
#
|
336
|
+
# @raise [RuntimeError]
|
337
|
+
# if the result is frozen
|
338
|
+
#
|
339
|
+
def _assert_not_frozen!
|
340
|
+
fail 'This result vault may no longer be modified' if frozen?
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
##
|
345
|
+
# Raise an exception if the provided value is not an Expection
|
346
|
+
#
|
347
|
+
def _assert_valid_exception(exception)
|
348
|
+
return if exception.is_a?(Exception)
|
349
|
+
fail ArgumentError, "The :exception= method will only accept an Exception instance, such as RuntimeError or AurgumentError"
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: result_vault
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- CodeMeister
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: " When your method needs to return more than a single value, ResultVault
|
14
|
+
is a pure ruby solution that lets you add all the extra bits you need while
|
15
|
+
still returning a single object. "
|
16
|
+
email:
|
17
|
+
- result_vault@codemeister.dev
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/result_vault.rb
|
23
|
+
- lib/result_vault/version.rb
|
24
|
+
homepage: https://github.com/Rubology/result_vault
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
metadata:
|
28
|
+
homepage_uri: https://github.com/Rubology/result_vault
|
29
|
+
source_code_uri: https://github.com/Rubology/result_vault
|
30
|
+
changelog_uri: https://github.com/Rubology/result_vault/blob/master/CHANGELOG.md
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 2.7.0
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.5.5
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: When your method needs to return more than a single value.
|
50
|
+
test_files: []
|