skn_utils 5.4.0 → 5.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +2 -0
  3. data/README.md +223 -72
  4. data/_config.yml +4 -4
  5. data/bin/concurrent_test_block +54 -0
  6. data/bin/concurrent_test_grouped +45 -0
  7. data/bin/concurrent_test_procs +45 -0
  8. data/bin/concurrent_test_wrapped +49 -0
  9. data/lib/skn_container.rb +2 -1
  10. data/lib/skn_failure.rb +2 -0
  11. data/lib/skn_hash.rb +2 -0
  12. data/lib/skn_registry.rb +25 -5
  13. data/lib/skn_settings.rb +2 -0
  14. data/lib/skn_success.rb +2 -0
  15. data/lib/skn_utils.rb +13 -2
  16. data/lib/skn_utils/concurrent_jobs.rb +117 -0
  17. data/lib/skn_utils/configurable.rb +55 -6
  18. data/lib/skn_utils/configuration.rb +2 -0
  19. data/lib/skn_utils/core_extensions.rb +29 -0
  20. data/lib/skn_utils/dotted_hash.rb +1 -0
  21. data/lib/skn_utils/env_string_handler.rb +2 -0
  22. data/lib/skn_utils/http_processor.rb +34 -0
  23. data/lib/skn_utils/job_commands.rb +247 -0
  24. data/lib/skn_utils/nested_result.rb +2 -0
  25. data/lib/skn_utils/notifier_base.rb +2 -0
  26. data/lib/skn_utils/null_object.rb +2 -0
  27. data/lib/skn_utils/page_controls.rb +2 -0
  28. data/lib/skn_utils/result_bean.rb +2 -0
  29. data/lib/skn_utils/version.rb +3 -1
  30. data/lib/skn_utils/wrappable.rb +32 -0
  31. data/skn_utils.gemspec +27 -22
  32. data/spec/lib/skn_utils/concurrent_jobs_spec.rb +279 -0
  33. data/spec/lib/skn_utils/configurable_spec.rb +23 -36
  34. data/spec/lib/skn_utils/registry_spec.rb +22 -0
  35. data/spec/lib/skn_utils/wrappers_spec.rb +80 -0
  36. data/spec/spec_helper.rb +5 -0
  37. data/spec/support/configurables.rb +36 -0
  38. data/spec/support/xml_matchers.rb +121 -0
  39. metadata +71 -24
  40. data/README.rdoc +0 -379
@@ -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.0
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: 2018-12-16 00:00:00.000000000 Z
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: '10'
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: '10'
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
- description: "The intent of the NestedResult class is to be a container for data values
140
- composed of key/value pairs, \nwith easy access to its contents, and on-demand transformation
141
- back to the hash (#to_hash).\n\nReview the RSpec tests, and or review the README
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.6.14
272
+ rubygems_version: 2.7.9
230
273
  signing_key:
231
274
  specification_version: 4
232
- summary: SknUtils contains a small collection of Ruby utilities, the first being a
233
- NestedResult a key/value container.
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
@@ -1,379 +0,0 @@
1
- [![Gem Version](https://badge.fury.io/rb/skn_utils.svg)](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
- ```