skn_utils 2.0.6 → 3.0.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 +4 -4
- data/.ruby-version +1 -1
- data/README.md +108 -149
- data/README.rdoc +130 -161
- data/bin/console +8 -0
- data/lib/skn_utils/exploring/configuration.rb +6 -6
- data/lib/skn_utils/nested_result.rb +382 -0
- data/lib/skn_utils/notifier_base.rb +94 -0
- data/lib/skn_utils/version.rb +2 -2
- data/lib/skn_utils.rb +1 -6
- data/skn_utils.gemspec +4 -20
- data/spec/lib/skn_utils/nested_result_spec.rb +268 -0
- data/spec/spec_helper.rb +2 -1
- metadata +27 -36
- data/lib/skn_utils/attribute_helpers.rb +0 -188
- data/lib/skn_utils/generic_bean.rb +0 -20
- data/lib/skn_utils/nested_result_base.rb +0 -123
- data/lib/skn_utils/page_controls.rb +0 -21
- data/lib/skn_utils/result_bean.rb +0 -17
- data/lib/skn_utils/value_bean.rb +0 -20
- data/spec/lib/skn_utils/generic_bean_spec.rb +0 -96
- data/spec/lib/skn_utils/page_controls_spec.rb +0 -124
- data/spec/lib/skn_utils/result_bean_spec.rb +0 -98
- data/spec/lib/skn_utils/value_bean_spec.rb +0 -96
- data/spec/support/shared_example_marshalable_ruby_pojo.rb +0 -54
- data/spec/support/shared_example_ruby_pojo.rb +0 -60
data/README.rdoc
CHANGED
@@ -1,98 +1,98 @@
|
|
1
1
|
[](http://badge.fury.io/rb/skn_utils)
|
2
2
|
|
3
|
-
= SknUtils
|
4
|
-
|
5
|
-
|
6
|
-
instance variables can be added post-create by 'obj.my_new_var = "some value"', or simply assigning it.
|
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).
|
7
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.
|
8
10
|
|
9
|
-
|
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.
|
11
15
|
|
12
|
-
* Transforms the initialization hash into object instance variables, with their Keys as the variable names
|
13
|
-
* If the key's value is also a hash, it too can optionally become an Object.
|
14
|
-
* if the key's value is a Array of Hashes, each element of the Array can optionally become an Object.
|
15
|
-
|
16
|
-
This nesting action is controlled by the value of the options key ':depth'.
|
17
|
-
The key :depth defaults to :multi, and has options of :single, :multi, or :multi_with_arrays
|
18
|
-
|
19
|
-
The ability of the resulting Object to be Marshalled(dump/load) can be preserved by merging configuration options
|
20
|
-
into the input params key ':enable_serialization' set to true. It defaults to false for speed purposes
|
21
|
-
|
22
16
|
|
23
|
-
|
24
|
-
|
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!
|
25
27
|
|
26
28
|
08/2016 V2.0.3
|
27
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)
|
28
30
|
I don't support his approach, but the CreateTask class caught my attention as a Rubyist.
|
29
31
|
|
30
|
-
12/2015 V2.0
|
32
|
+
12/2015 V2.0
|
31
33
|
All references to ActiveRecord or Rails has been removed to allow use in non-Rails environments
|
32
34
|
as a result serialization is done with standard Ruby Hash serialization methods; by first transforming
|
33
|
-
object back to a hash using its #to_hash method.
|
35
|
+
object back to a hash using its #to_hash method.
|
34
36
|
|
35
37
|
06/2015 V1.5.1 commit #67ef656
|
36
38
|
Last Version to depend on Rails (ActiveModel) for #to_json and #to_xml serialization
|
37
39
|
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
:enable_serialization = false -- [ true | false ], for speed, omits creation of attr_accessor
|
43
|
-
:depth = :multi -- [ :single | :multi | :multi_with_arrays ]
|
44
|
-
|
41
|
+
== Configuration Options
|
42
|
+
None required other than initialization hash
|
45
43
|
|
46
|
-
=== Public Methods
|
47
|
-
--------------------------------
|
48
44
|
|
45
|
+
== Public Methods
|
49
46
|
Each concrete Class supports the following utility methods:
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
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
|
54
51
|
#[] -- returns value of attr, when #[<attr_name_symbol>]
|
55
52
|
#[]=(attr, value) -- assigns value to existing attr, or creates a new key/value pair
|
56
|
-
#clear_<attr> -- assigns nil to existing attr, when #clear_attr
|
57
53
|
#<attr>? -- detects true/false presence? of attr, and non-blank existance of attr's value; when #address?
|
58
54
|
#<attr> -- returns value of named attribute
|
59
55
|
#<attr> = (value) -- assigns value to existing attr, or creates a new key/value pair
|
60
|
-
-- Where <attr> is a key value from the initial hash, or a key that was dynamically added
|
56
|
+
-- Where <attr> is a key value from the initial hash, or a key that was/will be dynamically added
|
57
|
+
|
58
|
+
|
61
59
|
|
60
|
+
== Public Components
|
61
|
+
SknUtils::NestedResult # >= V 3.0.0 Primary Key/Value Container with Dot/Hash notiation support.
|
62
62
|
|
63
|
-
=== Public Components
|
64
|
-
--------------------------------
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
SknUtils::
|
70
|
-
|
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.
|
71
72
|
|
72
73
|
|
73
74
|
== Basic features include:
|
74
75
|
```ruby
|
75
|
-
- provides the hash or dot notation methods of accessing values
|
76
|
-
'obj = SknUtils::ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
77
|
-
'x = obj.value1' or 'x = obj.value2.one'
|
78
|
-
'x = obj["value1"]'
|
79
|
-
'x = obj[:value1]'
|
76
|
+
- provides the hash or dot notation methods of accessing values:
|
80
77
|
|
81
|
-
|
82
|
-
|
83
|
-
|
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]
|
84
83
|
|
85
|
-
|
86
|
-
|
87
|
-
person.to_hash.to_json # => "{\"name\":\"Bob\"}"
|
88
|
-
person.to_hash.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<page-controls>\n <name>Bob</name>\n</page-controls>\n"
|
89
|
-
dmp = Marshal.dump(person) # => "\x04\bo:\x1ASknUtils::PageControls\x06:\n@nameI\"\bBob\x06:\x06ET"
|
90
|
-
person = Marshal.load(dmp) # => #<SknUtils::PageControls:0x007faede906d40 @name="Bob">
|
84
|
+
- enables serialization:
|
85
|
+
Internally supports #to_hash and #to_json
|
91
86
|
|
92
|
-
|
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">
|
93
92
|
|
94
93
|
- post create additions:
|
95
|
-
|
94
|
+
|
95
|
+
'obj = SknUtils::NestedResult.new({value1: "some value", value2: {one: 1, two: "two"}})
|
96
96
|
'x = obj.one' --causes NoMethodError
|
97
97
|
'x = obj.one = 'some other value' --creates a new instance value with accessors
|
98
98
|
'x = obj.one = {key1: 1, two: "two"}' --creates a new ***bean as the value of obj.one
|
@@ -100,129 +100,94 @@ into the input params key ':enable_serialization' set to true. It defaults to f
|
|
100
100
|
'y = obj.one[:two] --returns "two"
|
101
101
|
'y = obj.one['two'] --returns "two"
|
102
102
|
|
103
|
-
- supports predicates <attr>?
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
107
109
|
```
|
108
110
|
|
109
|
-
The combination of this NestedResultBase(dot notation class) and AttributeHelpers(hash notation module), produces this effect given the same params hash:
|
110
111
|
|
111
|
-
|
112
|
-
---------------------------------------------------- -----------------------------------------------------------------
|
112
|
+
== Usage:
|
113
113
|
|
114
|
-
|
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
|
115
116
|
```ruby
|
116
|
-
|
117
|
-
|
118
|
-
two: "two" drb.two.two = NoMethodError
|
119
|
-
},
|
120
|
-
three: [ {one: 'one', two: 2}, drb.three = [{one: 'one', two: 2},{three: 'three', four: 4}]
|
121
|
-
{three: 'three', four: 4} drb.three[1] = {three: 'three', four: 4}
|
122
|
-
] drb.three[1].four = NoMethodError
|
123
|
-
}
|
124
|
-
```
|
117
|
+
drb = SknUtils::NestedResult.new(params) Basic dot notation:
|
118
|
+
---------------------------------------------------- -----------------------------------------------------------------
|
125
119
|
|
126
|
-
(Follow VALUES that are Hashes only.) :depth => :multi
|
127
|
-
```ruby
|
128
|
-
* params = {one: 1, drb.one = 1
|
129
|
-
two: { one: 1, drb.two = <SknUtils::ResultBean>
|
130
|
-
two: "two" drb.two.two = 'two'
|
131
|
-
},
|
132
|
-
three: [ {one: 'one', two: 2}, drb.three = [{one: 'one', two: 2},{three: 'three', four: 4}]
|
133
|
-
{three: 'three', four: 4} drb.three[1] = {three: 'three', four: 4}
|
134
|
-
] drb.three[1].four = NoMethodError
|
135
|
-
}
|
136
|
-
```
|
137
|
-
|
138
|
-
(Follow VALUES that are Hashes and/or Arrays of Hashes) :depth => :multi_with_arrays
|
139
|
-
```ruby
|
140
120
|
* params = {one: 1, drb.one = 1
|
141
|
-
two: { one: 1,
|
142
|
-
|
143
|
-
|
144
|
-
three: [ {one: 'one', two: 2}, drb.three
|
145
|
-
{three: 'three', four: 4} drb.three[1] =
|
146
|
-
]
|
147
|
-
|
148
|
-
|
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
|
+
}
|
149
137
|
```
|
150
|
-
= Usage:
|
151
138
|
|
152
|
-
|
139
|
+
* Expected usage
|
153
140
|
```ruby
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
158
150
|
end
|
159
151
|
```
|
160
152
|
|
161
|
-
|
153
|
+
|
154
|
+
* Wrap additional methods around the core NestedResult feature set
|
162
155
|
```ruby
|
163
|
-
class MyPackage < SknUtils::
|
164
|
-
# defaults to :multi level
|
165
|
-
end
|
166
|
-
|
167
|
-
-- or --
|
168
|
-
|
169
|
-
class MyPackage < SknUtils::NestedResultBase
|
156
|
+
class MyPackage < SknUtils::NestedResult
|
170
157
|
def initialize(params={})
|
171
|
-
|
172
|
-
super(params) # default taken
|
158
|
+
super
|
173
159
|
end
|
174
|
-
end
|
175
|
-
|
176
|
-
-- or --
|
177
|
-
|
178
|
-
class MyPackage < SknUtils::NestedResultBase
|
179
|
-
def initialize(params={})
|
180
|
-
# your other init stuff here
|
181
|
-
super( params.merge({depth: :multi}) ) # Specified
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
** - or -- enable serialization and default to multi
|
186
|
-
class MyPackage < SknUtils::NestedResultBase
|
187
|
-
def initialize(params={})
|
188
|
-
super( params.merge({enable_serialization: true}) ) # Specified with Serialization Enabled
|
189
|
-
end
|
190
|
-
end
|
191
|
-
```
|
192
160
|
|
193
|
-
|
194
|
-
|
195
|
-
class MyPackage < SknUtils::NestedResultBase
|
196
|
-
def initialize(params={})
|
197
|
-
super( params.merge({depth: :multi_with_arrays, enable_serialization: true}) ) # override defaults
|
161
|
+
def additional_method
|
162
|
+
# do something
|
198
163
|
end
|
199
164
|
end
|
200
165
|
```
|
201
166
|
|
202
167
|
|
203
|
-
NOTE: Cannot be Marshalled/Serialized unless input params.merge({enable_serialization: true}) -- default is false
|
204
|
-
Use GenericBean or PageControls if serialization is needed, they initialize with this value true.
|
205
|
-
|
206
168
|
== Installation
|
207
|
-
----------------
|
208
|
-
runtime prereqs:
|
209
169
|
|
170
|
+
runtime prereqs:
|
171
|
+
V3+ None
|
210
172
|
V2+ None
|
211
173
|
V1+ gem 'active_model', '~> 3.0'
|
212
174
|
|
175
|
+
|
213
176
|
Add this line to your application's Gemfile:
|
177
|
+
```ruby
|
178
|
+
gem 'skn_utils'
|
179
|
+
```
|
214
180
|
|
215
|
-
gem 'skn_utils'
|
216
181
|
|
217
182
|
And then execute:
|
183
|
+
$ bundle
|
218
184
|
|
219
|
-
$ bundle install
|
220
185
|
|
221
186
|
Or install it yourself as:
|
222
|
-
|
223
187
|
$ gem install skn_utils
|
224
188
|
|
225
|
-
|
189
|
+
|
190
|
+
== Build
|
226
191
|
|
227
192
|
1. $ git clone git@github.com:skoona/skn_utils.git
|
228
193
|
2. $ cd skn_utils
|
@@ -233,27 +198,30 @@ Or install it yourself as:
|
|
233
198
|
7. $ gem install skn_utils
|
234
199
|
* Done
|
235
200
|
|
236
|
-
|
201
|
+
|
202
|
+
== Console Workout
|
237
203
|
|
238
204
|
Start with building gem first.
|
239
|
-
```bash
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
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
|
252
220
|
```
|
253
|
-
|
221
|
+
|
254
222
|
== Contributing
|
255
223
|
|
256
|
-
1. Fork it
|
224
|
+
1. Fork it
|
257
225
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
258
226
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
259
227
|
4. Push to the branch (`git push origin my-new-feature`)
|
@@ -262,4 +230,5 @@ Start with building gem first.
|
|
262
230
|
|
263
231
|
== License
|
264
232
|
|
265
|
-
MIT.
|
233
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
234
|
+
|
data/bin/console
ADDED
@@ -11,14 +11,14 @@ module SknUtils
|
|
11
11
|
module_function
|
12
12
|
|
13
13
|
def option_defaults
|
14
|
-
|
14
|
+
@option_defaults ||= {one: 1, two: 2, three: 3}
|
15
15
|
end
|
16
16
|
def option_defaults=(parms)
|
17
|
-
|
17
|
+
@option_defaults = parms
|
18
18
|
end
|
19
19
|
|
20
20
|
def reset!
|
21
|
-
|
21
|
+
@configuration = Options.new(option_defaults)
|
22
22
|
true
|
23
23
|
end
|
24
24
|
|
@@ -27,9 +27,9 @@ module SknUtils
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def configure # Initialize with both the configuration keys and default values
|
30
|
-
|
31
|
-
yield(
|
32
|
-
|
30
|
+
@configuration || reset!
|
31
|
+
yield(@configuration) if block_given?
|
32
|
+
@configuration
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|