skn_utils 5.4.0 → 5.8.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/.rspec +2 -0
- data/README.md +223 -72
- data/_config.yml +4 -4
- data/bin/concurrent_test_block +54 -0
- data/bin/concurrent_test_grouped +45 -0
- data/bin/concurrent_test_procs +45 -0
- data/bin/concurrent_test_wrapped +49 -0
- data/lib/skn_container.rb +2 -1
- data/lib/skn_failure.rb +2 -0
- data/lib/skn_hash.rb +2 -0
- data/lib/skn_registry.rb +25 -5
- data/lib/skn_settings.rb +2 -0
- data/lib/skn_success.rb +2 -0
- data/lib/skn_utils.rb +13 -2
- data/lib/skn_utils/concurrent_jobs.rb +117 -0
- data/lib/skn_utils/configurable.rb +55 -6
- data/lib/skn_utils/configuration.rb +2 -0
- data/lib/skn_utils/core_extensions.rb +29 -0
- data/lib/skn_utils/dotted_hash.rb +1 -0
- data/lib/skn_utils/env_string_handler.rb +2 -0
- data/lib/skn_utils/http_processor.rb +34 -0
- data/lib/skn_utils/job_commands.rb +247 -0
- data/lib/skn_utils/nested_result.rb +2 -0
- data/lib/skn_utils/notifier_base.rb +2 -0
- data/lib/skn_utils/null_object.rb +2 -0
- data/lib/skn_utils/page_controls.rb +2 -0
- data/lib/skn_utils/result_bean.rb +2 -0
- data/lib/skn_utils/version.rb +3 -1
- data/lib/skn_utils/wrappable.rb +32 -0
- data/skn_utils.gemspec +27 -22
- data/spec/lib/skn_utils/concurrent_jobs_spec.rb +279 -0
- data/spec/lib/skn_utils/configurable_spec.rb +23 -36
- data/spec/lib/skn_utils/registry_spec.rb +22 -0
- data/spec/lib/skn_utils/wrappers_spec.rb +80 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/configurables.rb +36 -0
- data/spec/support/xml_matchers.rb +121 -0
- metadata +71 -24
- data/README.rdoc +0 -379
data/spec/spec_helper.rb
CHANGED
@@ -15,6 +15,9 @@ end
|
|
15
15
|
require 'skn_utils'
|
16
16
|
require 'rspec'
|
17
17
|
|
18
|
+
require 'webmock/rspec'
|
19
|
+
require 'support/xml_matchers'
|
20
|
+
|
18
21
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
19
22
|
RSpec.configure do |config|
|
20
23
|
Kernel.srand config.seed
|
@@ -30,6 +33,8 @@ RSpec.configure do |config|
|
|
30
33
|
# config.disable_monkey_patching! # -- breaks rspec runtime
|
31
34
|
config.warnings = true
|
32
35
|
|
36
|
+
config.include WebMock::API
|
37
|
+
|
33
38
|
if config.files_to_run.one?
|
34
39
|
config.formatter = :documentation
|
35
40
|
else
|
@@ -0,0 +1,36 @@
|
|
1
|
+
##
|
2
|
+
# spec/support/configurables.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class MyApp
|
6
|
+
include SknUtils::Configurable.with( :app_id, :title, :cookie_name, enable_root: true) # No options hash defaults to true
|
7
|
+
# - and accept defaults for #env=, #root=, #registry=, and #logger=
|
8
|
+
|
9
|
+
# notice: self.logger=, the self is required when assigning values
|
10
|
+
self.logger = Object.new
|
11
|
+
self.registry = Object.new
|
12
|
+
|
13
|
+
configure do
|
14
|
+
app_id 'some app'
|
15
|
+
title 'My Title'
|
16
|
+
cookie_name 'Chocolate'
|
17
|
+
end
|
18
|
+
|
19
|
+
def null_value
|
20
|
+
self.class.config.app_id.dup
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module MyMod
|
25
|
+
include SknUtils::Configurable.with(:app_id, :title, :cookie_name, enable_root: false)
|
26
|
+
|
27
|
+
def self.null_value
|
28
|
+
config.app_id.dup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
MyMod.configure do
|
33
|
+
app_id 'some module'
|
34
|
+
title 'Some Title'
|
35
|
+
cookie_name 'Caramel'
|
36
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# ##
|
2
|
+
# File: <spec>/xml_matchers.rb
|
3
|
+
#
|
4
|
+
# Refs: https://github.com/sparklemotion/nokogiri/wiki/Cheat-sheet
|
5
|
+
# https://arjanvandergaag.nl/blog/rspec-matchers.html
|
6
|
+
# http://blog.wolfman.com/articles/2008/1/2/xpath-matchers-for-rspec
|
7
|
+
# https://semaphoreci.com/community/tutorials/how-to-use-custom-rspec-matchers-to-specify-behaviour
|
8
|
+
#
|
9
|
+
|
10
|
+
# Useage
|
11
|
+
# ----------------------------------------------------------------------
|
12
|
+
# expect(bundle).to have_xpath('//witnesses/witness/role')
|
13
|
+
# expect(bundle).to have_nodes('//witnesses/witness/role', 3)
|
14
|
+
# expect(bundle).to match_xpath('//lossInformation/date', "2020-01-28")
|
15
|
+
|
16
|
+
# check if the xpath exists one or more times
|
17
|
+
class HaveXpath
|
18
|
+
def initialize(xpath)
|
19
|
+
@xpath = xpath
|
20
|
+
end
|
21
|
+
|
22
|
+
def matches?(str)
|
23
|
+
@str = str
|
24
|
+
xml_document.xpath(@xpath).any?
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message
|
28
|
+
"Expected xpath #{@xpath.inspect} to match in:\n" + pretty_printed_xml
|
29
|
+
end
|
30
|
+
|
31
|
+
def failure_message_when_negated
|
32
|
+
"Expected xpath #{@xpath.inspect} not to match in:\n" + pretty_printed_xml
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def pretty_printed_xml
|
38
|
+
xml_document.to_xml(indent: 2)
|
39
|
+
end
|
40
|
+
|
41
|
+
def xml_document
|
42
|
+
@xml_document ||= Nokogiri::XML(@str)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def have_xpath(*xpath)
|
47
|
+
HaveXpath.new(*xpath)
|
48
|
+
end
|
49
|
+
|
50
|
+
# check if the xpath has the specified value
|
51
|
+
# value is a string and there must be a single result to match its
|
52
|
+
# equality against
|
53
|
+
class MatchXpath
|
54
|
+
def initialize(xpath, val)
|
55
|
+
@xpath = xpath
|
56
|
+
@val= val
|
57
|
+
end
|
58
|
+
|
59
|
+
def matches?(response)
|
60
|
+
@response = response
|
61
|
+
doc = response.is_a?(Nokogiri::XML::Document) ? response : Nokogiri::XML(@response)
|
62
|
+
ok= true
|
63
|
+
doc.xpath(@xpath).each do |e|
|
64
|
+
@actual_val= case e
|
65
|
+
when Nokogiri::XML::Attr
|
66
|
+
e.to_s
|
67
|
+
when Nokogiri::XML::Element
|
68
|
+
e.text
|
69
|
+
else
|
70
|
+
e.to_s
|
71
|
+
end
|
72
|
+
return false unless @val == @actual_val
|
73
|
+
end
|
74
|
+
return ok
|
75
|
+
end
|
76
|
+
|
77
|
+
def failure_message
|
78
|
+
"The xpath #{@xpath} did not have the value '#{@val}' \n It was '#{@actual_val}'"
|
79
|
+
end
|
80
|
+
|
81
|
+
def failure_message_when_negated
|
82
|
+
"The xpath #{@xpath} has the value '#{@val}' \n Was expected not to match '#{@actual_val}'"
|
83
|
+
end
|
84
|
+
|
85
|
+
def description
|
86
|
+
"match the xpath expression #{@xpath} with #{@val}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def match_xpath(xpath, val)
|
91
|
+
MatchXpath.new(xpath, val)
|
92
|
+
end
|
93
|
+
|
94
|
+
# checks if the given xpath occurs num times
|
95
|
+
class HaveNodes #:nodoc:
|
96
|
+
def initialize(xpath, num)
|
97
|
+
@xpath= xpath
|
98
|
+
@num = num
|
99
|
+
end
|
100
|
+
|
101
|
+
def matches?(response)
|
102
|
+
@response = response
|
103
|
+
doc = response.is_a?(Nokogiri::XML::Document) ? response : Nokogiri::XML(@response)
|
104
|
+
matches = doc.xpath(@xpath)
|
105
|
+
@num_found= matches.size
|
106
|
+
@num_found == @num
|
107
|
+
end
|
108
|
+
|
109
|
+
def failure_message
|
110
|
+
"Did not find expected number of nodes #{@num} in xpath #{@xpath} \n Found #{@num_found}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def description
|
114
|
+
"match the number of nodes #{@num}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def have_nodes(xpath, num)
|
119
|
+
HaveNodes.new(xpath, num)
|
120
|
+
end
|
121
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skn_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Scott Jr
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deep_merge
|
@@ -56,94 +56,126 @@ dependencies:
|
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 12.3.3
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 12.3.3
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: pry
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-coolline
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: simplecov
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- - "
|
129
|
+
- - ">="
|
116
130
|
- !ruby/object:Gem::Version
|
117
131
|
version: '0'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
|
-
- - "
|
136
|
+
- - ">="
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: benchmark-ips
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
|
-
- - "
|
143
|
+
- - ">="
|
130
144
|
- !ruby/object:Gem::Version
|
131
145
|
version: '2'
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
|
-
- - "
|
150
|
+
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '2'
|
139
|
-
|
140
|
-
|
141
|
-
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: webmock
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description: "Value containers supporting nested dot.notation access over hashes,
|
168
|
+
and utilities offering dependency injection/lookup, and \nlanguage extensions support
|
169
|
+
running in a non-rails environment. Plus, examples of null objects, class customization,
|
170
|
+
\nand concurrent processing.\n\nReview the RSpec tests, and or review the README
|
142
171
|
for more details.\n"
|
143
172
|
email: skoona@gmail.com
|
144
173
|
executables: []
|
145
174
|
extensions: []
|
146
|
-
extra_rdoc_files:
|
175
|
+
extra_rdoc_files:
|
176
|
+
- README.md
|
177
|
+
- CODE_OF_CONDUCT.md
|
178
|
+
- LICENSE
|
147
179
|
files:
|
148
180
|
- ".gitignore"
|
149
181
|
- ".rspec"
|
@@ -152,10 +184,13 @@ files:
|
|
152
184
|
- Gemfile
|
153
185
|
- LICENSE
|
154
186
|
- README.md
|
155
|
-
- README.rdoc
|
156
187
|
- Rakefile
|
157
188
|
- _config.yml
|
158
189
|
- bin/bench_nested_result.rb
|
190
|
+
- bin/concurrent_test_block
|
191
|
+
- bin/concurrent_test_grouped
|
192
|
+
- bin/concurrent_test_procs
|
193
|
+
- bin/concurrent_test_wrapped
|
159
194
|
- bin/configs/settings.yml
|
160
195
|
- bin/configs/settings/development.yml
|
161
196
|
- bin/configs/settings/production.yml
|
@@ -172,17 +207,21 @@ files:
|
|
172
207
|
- lib/skn_settings.rb
|
173
208
|
- lib/skn_success.rb
|
174
209
|
- lib/skn_utils.rb
|
210
|
+
- lib/skn_utils/concurrent_jobs.rb
|
175
211
|
- lib/skn_utils/configurable.rb
|
176
212
|
- lib/skn_utils/configuration.rb
|
177
213
|
- lib/skn_utils/core_extensions.rb
|
178
214
|
- lib/skn_utils/dotted_hash.rb
|
179
215
|
- lib/skn_utils/env_string_handler.rb
|
216
|
+
- lib/skn_utils/http_processor.rb
|
217
|
+
- lib/skn_utils/job_commands.rb
|
180
218
|
- lib/skn_utils/nested_result.rb
|
181
219
|
- lib/skn_utils/notifier_base.rb
|
182
220
|
- lib/skn_utils/null_object.rb
|
183
221
|
- lib/skn_utils/page_controls.rb
|
184
222
|
- lib/skn_utils/result_bean.rb
|
185
223
|
- lib/skn_utils/version.rb
|
224
|
+
- lib/skn_utils/wrappable.rb
|
186
225
|
- skn_utils.gemspec
|
187
226
|
- spec/factories/environments/development.yml
|
188
227
|
- spec/factories/environments/production.yml
|
@@ -195,6 +234,7 @@ files:
|
|
195
234
|
- spec/lib/skn_settings_spec.rb
|
196
235
|
- spec/lib/skn_utils/as_human_size_spec.rb
|
197
236
|
- spec/lib/skn_utils/catch_exceptions_spec.rb
|
237
|
+
- spec/lib/skn_utils/concurrent_jobs_spec.rb
|
198
238
|
- spec/lib/skn_utils/configurable_spec.rb
|
199
239
|
- spec/lib/skn_utils/container_spec.rb
|
200
240
|
- spec/lib/skn_utils/nested_result_spec.rb
|
@@ -202,7 +242,10 @@ files:
|
|
202
242
|
- spec/lib/skn_utils/null_object_spec.rb
|
203
243
|
- spec/lib/skn_utils/registry_spec.rb
|
204
244
|
- spec/lib/skn_utils/success_failure_value_container_spec.rb
|
245
|
+
- spec/lib/skn_utils/wrappers_spec.rb
|
205
246
|
- spec/spec_helper.rb
|
247
|
+
- spec/support/configurables.rb
|
248
|
+
- spec/support/xml_matchers.rb
|
206
249
|
homepage: https://github.com/skoona/skn_utils
|
207
250
|
licenses:
|
208
251
|
- MIT
|
@@ -226,11 +269,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
226
269
|
version: '0'
|
227
270
|
requirements: []
|
228
271
|
rubyforge_project:
|
229
|
-
rubygems_version: 2.
|
272
|
+
rubygems_version: 2.7.9
|
230
273
|
signing_key:
|
231
274
|
specification_version: 4
|
232
|
-
summary:
|
233
|
-
|
275
|
+
summary: Ruby utilities for dependency injection/lookup, class customizations, and
|
276
|
+
dot.notion access over nested hashes.
|
234
277
|
test_files:
|
235
278
|
- spec/factories/environments/development.yml
|
236
279
|
- spec/factories/environments/production.yml
|
@@ -243,6 +286,7 @@ test_files:
|
|
243
286
|
- spec/lib/skn_settings_spec.rb
|
244
287
|
- spec/lib/skn_utils/as_human_size_spec.rb
|
245
288
|
- spec/lib/skn_utils/catch_exceptions_spec.rb
|
289
|
+
- spec/lib/skn_utils/concurrent_jobs_spec.rb
|
246
290
|
- spec/lib/skn_utils/configurable_spec.rb
|
247
291
|
- spec/lib/skn_utils/container_spec.rb
|
248
292
|
- spec/lib/skn_utils/nested_result_spec.rb
|
@@ -250,4 +294,7 @@ test_files:
|
|
250
294
|
- spec/lib/skn_utils/null_object_spec.rb
|
251
295
|
- spec/lib/skn_utils/registry_spec.rb
|
252
296
|
- spec/lib/skn_utils/success_failure_value_container_spec.rb
|
297
|
+
- spec/lib/skn_utils/wrappers_spec.rb
|
253
298
|
- spec/spec_helper.rb
|
299
|
+
- spec/support/configurables.rb
|
300
|
+
- spec/support/xml_matchers.rb
|
data/README.rdoc
DELETED
@@ -1,379 +0,0 @@
|
|
1
|
-
[](http://badge.fury.io/rb/skn_utils)
|
2
|
-
|
3
|
-
= SknUtils
|
4
|
-
==== SknUtils::NestedResult class; dynamic key/value container
|
5
|
-
The intent of this gem is to be a container of data results or key/value pairs, with easy access to its contents, and on-demand transformation back to the hash (#to_hash).
|
6
|
-
|
7
|
-
Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated at runtime with an input hash. This library creates
|
8
|
-
an Object with Dot or Hash notational accessors to each key's value. Additional key/value pairs can be added post-create
|
9
|
-
by 'obj.my_new_var = "some value"', or simply assigning it.
|
10
|
-
|
11
|
-
* Transforms the initialization hash into accessable object instance values, with their keys as method names.
|
12
|
-
* If the key's value is also a hash, it too will become an Object.
|
13
|
-
* if the key's value is a Array of Hashes, or Array of Arrays of Hashes, each element of the Arrays will become an Object.
|
14
|
-
* The current key/value (including nested) pairs are returned via #to_hash or #to_json when and if needed.
|
15
|
-
|
16
|
-
|
17
|
-
== New Features
|
18
|
-
03/2017 V3.0.0
|
19
|
-
Added SknUtils::NestedResult to replace, or be an alternate, to ResultBean, GenericBean, PageControls, ValueBean, and AttributeHelper.
|
20
|
-
NestedResult overcome issues with serialization via Marshal and Yaml/Psych.
|
21
|
-
NestedResult will properly encode all hash based key/value pairs of input and decodes it via #to_h or #to_json
|
22
|
-
NestedResult encodes everything given no matter how deeply its nested, unlike the prior version where you had control over nesting.
|
23
|
-
|
24
|
-
10/2016 V2.0.6
|
25
|
-
Added an SknUtils::NullObject and SknUtils::nullable?(value) extracted from [Avdi Grimm's Confident Code](https://gist.github.com/jschoolcraft/979827)
|
26
|
-
The NullObject class has great all around utility, check out it's specs!
|
27
|
-
|
28
|
-
08/2016 V2.0.3
|
29
|
-
Added an exploritory ActionService class and RSpec test, triggered by reading [Kamil Lelonek](https://blog.lelonek.me/what-service-objects-are-not-7abef8aa2f99#.p64vudxq4)
|
30
|
-
I don't support his approach, but the CreateTask class caught my attention as a Rubyist.
|
31
|
-
|
32
|
-
12/2015 V2.0
|
33
|
-
All references to ActiveRecord or Rails has been removed to allow use in non-Rails environments
|
34
|
-
as a result serialization is done with standard Ruby Hash serialization methods; by first transforming
|
35
|
-
object back to a hash using its #to_hash method.
|
36
|
-
|
37
|
-
06/2015 V1.5.1 commit #67ef656
|
38
|
-
Last Version to depend on Rails (ActiveModel) for #to_json and #to_xml serialization
|
39
|
-
|
40
|
-
|
41
|
-
== Configuration Options
|
42
|
-
None required other than initialization hash
|
43
|
-
|
44
|
-
|
45
|
-
== Public Methods
|
46
|
-
Each concrete Class supports the following utility methods:
|
47
|
-
#to_hash -- returns a hash of current key/value pairs, including nested
|
48
|
-
#to_json -- returns a json string of current key/value pairs, including nested
|
49
|
-
#hash_from(:base_key) -- exports the internal hash starting with this base level key
|
50
|
-
#obj.obj2.hash_from(:base) -- exports the internal hash starting from this nested base level key
|
51
|
-
#[] -- returns value of attr, when #[<attr_name_symbol>]
|
52
|
-
#[]=(attr, value) -- assigns value to existing attr, or creates a new key/value pair
|
53
|
-
#<attr>? -- detects true/false presence? of attr, and non-blank existance of attr's value; when #address?
|
54
|
-
#<attr> -- returns value of named attribute
|
55
|
-
#<attr> = (value) -- assigns value to existing attr, or creates a new key/value pair
|
56
|
-
-- Where <attr> is a key value from the initial hash, or a key that was/will be dynamically added
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
== Public Components
|
61
|
-
SknUtils::NestedResult # >= V 3.0.0 Primary Key/Value Container with Dot/Hash notiation support.
|
62
|
-
|
63
|
-
|
64
|
-
*** <= V 2.0.6 Depreciated, will be removed in next release ***
|
65
|
-
|
66
|
-
Inherit from NestedResultBase or instantiate an pre-built Class:
|
67
|
-
SknUtils::ResultBean # => Not Serializable and follows hash values only.
|
68
|
-
SknUtils::PageControls # => Serializable and follows hash values and arrays of hashes.
|
69
|
-
SknUtils::GenericBean # => Serializable and follows hash values only.
|
70
|
-
SknUtils::ValueBean # => Serializable and DOES NOT follows hash values.
|
71
|
-
or Include SknUtils::AttributeHelpers # => Adds getter/setters, and hash notation access to instance vars of any object.
|
72
|
-
|
73
|
-
|
74
|
-
== Basic features include:
|
75
|
-
```ruby
|
76
|
-
- provides the hash or dot notation methods of accessing values:
|
77
|
-
|
78
|
-
$ obj = SknUtils::NestedResult.new({value1: "some value", value2: {one: 1, two: "two"}})
|
79
|
-
$ x = obj.value1
|
80
|
-
$ x = obj.value2.one
|
81
|
-
$ x = obj["value1"]
|
82
|
-
$ x = obj[:value1]
|
83
|
-
|
84
|
-
- enables serialization:
|
85
|
-
Internally supports #to_hash and #to_json
|
86
|
-
|
87
|
-
$ person = SknUtils::NestedResult.new({name: "Bob"})
|
88
|
-
$ person.to_hash # => {"name"=>"Bob"}
|
89
|
-
$ person.to_json # => "{\"name\":\"Bob\"}"
|
90
|
-
$ dmp = Marshal.dump(person) # => "\x04\bo:\x1ASknUtils::NestedResult\x06:\n@nameI\"\bBob\x06:\x06ET"
|
91
|
-
$ person2 = Marshal.load(dmp) # => #<SknUtils::NestedResult:0x007faede906d40 @name="Bob">
|
92
|
-
|
93
|
-
- post create additions:
|
94
|
-
|
95
|
-
'obj = SknUtils::NestedResult.new({value1: "some value", value2: {one: 1, two: "two"}})
|
96
|
-
'x = obj.one' --causes NoMethodError
|
97
|
-
'x = obj.one = 'some other value' --creates a new instance value with accessors
|
98
|
-
'x = obj.one = {key1: 1, two: "two"}' --creates a new ***bean as the value of obj.one
|
99
|
-
'y = obj.one.two' --returns "two"
|
100
|
-
'y = obj.one[:two] --returns "two"
|
101
|
-
'y = obj.one['two'] --returns "two"
|
102
|
-
|
103
|
-
- supports predicates <attr>? method patterns: target must exist and have a non-empty/valid value
|
104
|
-
|
105
|
-
$ obj = SknUtils::NestedResult.new({name: "Something", active: false, phone: "2609998888"})'
|
106
|
-
$ obj.name?' # => true -- true or false, like obj.name.present?
|
107
|
-
$ obj.active? # => true -- your asking if method exist with a valid value, not what the value is!
|
108
|
-
$ obj.street? # => false
|
109
|
-
```
|
110
|
-
|
111
|
-
|
112
|
-
== Usage:
|
113
|
-
|
114
|
-
* The NestedResult produces these effects when given a params hash;
|
115
|
-
* Follow VALUES that are Hashes, Arrays of Hashes, and Arrays of Arrays of Hashes
|
116
|
-
```ruby
|
117
|
-
drb = SknUtils::NestedResult.new(params) Basic dot notation:
|
118
|
-
---------------------------------------------------- -----------------------------------------------------------------
|
119
|
-
|
120
|
-
* params = {one: 1, drb.one = 1
|
121
|
-
two: { one: 1, two: "two"}, drb.two = <SknUtils::NestedResult>
|
122
|
-
drb.two.two = 'two'
|
123
|
-
|
124
|
-
three: [ {one: 'one', two: 2}, drb.three.first.one = 'one'
|
125
|
-
{three: 'three', four: 4} drb.three[1].four = 4
|
126
|
-
], drb.three.last.three = 'three'
|
127
|
-
|
128
|
-
four: [
|
129
|
-
[ {one: 'one', two: 2}, drb.four.first.first.one = 'one'
|
130
|
-
{three: 'three', four: 4} ], drb.four.first.last.four = 4
|
131
|
-
[ { 5: 'five', 6: 'six'}, drb.four[1][0][5] = 'five' # number keys require hash notation :[]
|
132
|
-
{five: '5', six: 6} ] drb.four[1].last.six = 6
|
133
|
-
],
|
134
|
-
'five' => [1, 2, 3] drb.five = [1, 2, 3]
|
135
|
-
6 => 'number key' drb[6] = 'number key'
|
136
|
-
}
|
137
|
-
```
|
138
|
-
|
139
|
-
* Expected usage
|
140
|
-
```ruby
|
141
|
-
result = SknUtils::NestedResult.new({
|
142
|
-
success: true,
|
143
|
-
message: "",
|
144
|
-
payload: {package: 'of key/value pairs from operations'}
|
145
|
-
})
|
146
|
-
...
|
147
|
-
|
148
|
-
if result.success && result.payload.package?
|
149
|
-
# do something with result.payload
|
150
|
-
end
|
151
|
-
```
|
152
|
-
|
153
|
-
|
154
|
-
* Wrap additional methods around the core NestedResult feature set
|
155
|
-
```ruby
|
156
|
-
class MyPackage < SknUtils::NestedResult
|
157
|
-
def initialize(params={})
|
158
|
-
super
|
159
|
-
end
|
160
|
-
|
161
|
-
def additional_method
|
162
|
-
# do something
|
163
|
-
end
|
164
|
-
end
|
165
|
-
```
|
166
|
-
|
167
|
-
|
168
|
-
== Installation
|
169
|
-
|
170
|
-
runtime prereqs:
|
171
|
-
V3+ None
|
172
|
-
V2+ None
|
173
|
-
V1+ gem 'active_model', '~> 3.0'
|
174
|
-
|
175
|
-
|
176
|
-
Add this line to your application's Gemfile:
|
177
|
-
```ruby
|
178
|
-
gem 'skn_utils'
|
179
|
-
```
|
180
|
-
|
181
|
-
|
182
|
-
And then execute:
|
183
|
-
$ bundle
|
184
|
-
|
185
|
-
|
186
|
-
Or install it yourself as:
|
187
|
-
$ gem install skn_utils
|
188
|
-
|
189
|
-
|
190
|
-
== Build
|
191
|
-
|
192
|
-
1. $ git clone git@github.com:skoona/skn_utils.git
|
193
|
-
2. $ cd skn_utils
|
194
|
-
3. $ gem install bundler
|
195
|
-
4. $ bundle install
|
196
|
-
5. $ bundle exec rspec
|
197
|
-
6. $ gem build skn_utils.gemspec
|
198
|
-
7. $ gem install skn_utils
|
199
|
-
* Done
|
200
|
-
|
201
|
-
|
202
|
-
== Console Workout
|
203
|
-
|
204
|
-
Start with building gem first.
|
205
|
-
```bash
|
206
|
-
$ cd skn_utils
|
207
|
-
$ bin/console
|
208
|
-
|
209
|
-
[1] pry(main)> rb = SknUtils::NestedResult.new({sample: [{one: "one", two: "two"},{one: 1, two: 2}] })
|
210
|
-
[2] pry(main)> pg = SknUtils::NestedResult.new({sample: [{three: 3, four: 4},{five: 'five', two: 'two'}] })
|
211
|
-
[3] pry(main)> pg.sample.first.three
|
212
|
-
[4] pry(main)> rb.sample.first.one
|
213
|
-
[5] pry(main)> rb.sample.first[:one]
|
214
|
-
[6] pry(main)> rb.hash_from(:sample)
|
215
|
-
[7] pry(main)> rb.sample?
|
216
|
-
[8] pry(main)> rb.sample[0].one?
|
217
|
-
|
218
|
-
[n] pry(main)> exit
|
219
|
-
* Done
|
220
|
-
```
|
221
|
-
|
222
|
-
== Contributing
|
223
|
-
|
224
|
-
1. Fork it
|
225
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
226
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
227
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
228
|
-
5. Create a new Pull Request
|
229
|
-
|
230
|
-
|
231
|
-
== License
|
232
|
-
|
233
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
234
|
-
|
235
|
-
=== Notes:
|
236
|
-
```ruby
|
237
|
-
class ApplicationSchema < Dry::Validation::Schema
|
238
|
-
configure do |config|
|
239
|
-
option :record
|
240
|
-
option :machine_repository, Machine
|
241
|
-
option :user_repository, User
|
242
|
-
option :temporary_token_repository, TemporaryToken
|
243
|
-
|
244
|
-
config.messages_file = 'config/locales/validations.yml'
|
245
|
-
end
|
246
|
-
|
247
|
-
...
|
248
|
-
|
249
|
-
end
|
250
|
-
|
251
|
-
module Sessions
|
252
|
-
AuthenticateUserSchema = Dry::Validation.Schema(ApplicationSchema) do
|
253
|
-
required(:email).filled(:str?)
|
254
|
-
required(:password).filled(:str?)
|
255
|
-
|
256
|
-
validate(exists?: :email) do |email|
|
257
|
-
user_repository.find_by(email: email).present?
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
```
|
262
|
-
|
263
|
-
from: Andy Holland @AMHOL, roda-action
|
264
|
-
```ruby
|
265
|
-
class Roda
|
266
|
-
ContainerError = Class.new(::Exception)
|
267
|
-
|
268
|
-
module RodaPlugins
|
269
|
-
# The container plugin allows your application to
|
270
|
-
# act as a container, you can register values
|
271
|
-
# with your application (container) and resolve them later.
|
272
|
-
#
|
273
|
-
# If you register something that responds to call, the result of
|
274
|
-
# call will be returned each time you resolve it.
|
275
|
-
#
|
276
|
-
# Example:
|
277
|
-
#
|
278
|
-
# plugin :container
|
279
|
-
#
|
280
|
-
# class UserRepository
|
281
|
-
# def self.first
|
282
|
-
# { name: 'Jack' }
|
283
|
-
# end
|
284
|
-
# end
|
285
|
-
#
|
286
|
-
# MyApplication.register(:user_repository, UserRepository)
|
287
|
-
# MyApplication.resolve(:user_repository).first
|
288
|
-
#
|
289
|
-
# class PersonRepository
|
290
|
-
# def first
|
291
|
-
# { name: 'Gill' }
|
292
|
-
# end
|
293
|
-
# end
|
294
|
-
#
|
295
|
-
# MyApplication.register(:person_repository, -> { PersonRepository.new })
|
296
|
-
# MyApplication.resolve(:person_repository).first
|
297
|
-
module Container
|
298
|
-
class Container < RodaCache
|
299
|
-
def register(key, contents = nil, options = {}, &block)
|
300
|
-
if block_given?
|
301
|
-
item = block
|
302
|
-
options = contents if contents.is_a?(::Hash)
|
303
|
-
else
|
304
|
-
item = contents
|
305
|
-
end
|
306
|
-
|
307
|
-
self[key] = Content.new(item, options)
|
308
|
-
end
|
309
|
-
|
310
|
-
def resolve(key)
|
311
|
-
content = self.fetch(key) do
|
312
|
-
fail ::Roda::ContainerError, "Nothing registered with the name #{key}"
|
313
|
-
end
|
314
|
-
|
315
|
-
content.call
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
class Content
|
320
|
-
attr_reader :item, :options
|
321
|
-
|
322
|
-
def initialize(item, options = {})
|
323
|
-
@item, @options = item, {
|
324
|
-
call: item.is_a?(::Proc)
|
325
|
-
}.merge(options)
|
326
|
-
end
|
327
|
-
|
328
|
-
def call
|
329
|
-
if options[:call] == true
|
330
|
-
item.call
|
331
|
-
else
|
332
|
-
item
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
module ClassMethods
|
338
|
-
attr_reader :container
|
339
|
-
private :container
|
340
|
-
|
341
|
-
def self.extended(subclass)
|
342
|
-
subclass.instance_variable_set(:@container, Container.new)
|
343
|
-
super
|
344
|
-
end
|
345
|
-
|
346
|
-
def inherited(subclass)
|
347
|
-
subclass.instance_variable_set(:@container, container)
|
348
|
-
super
|
349
|
-
end
|
350
|
-
|
351
|
-
def instance
|
352
|
-
Thread.current[:__container__]
|
353
|
-
end
|
354
|
-
|
355
|
-
def register(key, contents = nil, options = {}, &block)
|
356
|
-
container.register(key, contents, options, &block)
|
357
|
-
end
|
358
|
-
|
359
|
-
def resolve(key)
|
360
|
-
container.resolve(key)
|
361
|
-
end
|
362
|
-
|
363
|
-
def detach_container
|
364
|
-
@container = container.dup
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
module InstanceMethods
|
369
|
-
def call(*args, &block)
|
370
|
-
Thread.current[:__container__] = self.class.send(:container).dup
|
371
|
-
super
|
372
|
-
end
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
register_plugin(:container, Container)
|
377
|
-
end
|
378
|
-
end
|
379
|
-
```
|