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 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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ResultVault
4
+ VERSION = "1.2.3"
5
+ end
@@ -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: []