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.
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
- ```