result_vault 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
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: []