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.
data/README.rdoc CHANGED
@@ -1,98 +1,98 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/skn_utils.svg)](http://badge.fury.io/rb/skn_utils)
2
2
 
3
- = SknUtils
4
- Ruby Gem containing a Ruby PORO (Plain Old Ruby Object) that can be instantiated at runtime with an input hash. This library creates
5
- an Object with instance variables and associated getters and setters for Dot or Hash notational access to each instance variable. Additional
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
- The intent of this gem is to be a container of data results, with easy access to its contents with on-demand transformation back to a hash (#to_hash)
10
- for easy serialization using standard ruby Hash serialization methods.
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
- === New Features
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
- === Configuration Options
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
- #depth_level -- returns parsing depth level, see :depth
51
- #serialization_required? -- returns true/false if serialization is enabled
52
- #to_hash -- returns a hash of all user attributes
53
- #to_hash(true) -- returns a hash of all user and internal attributes
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
- Inherit from NestedResultBase or instantiate a 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
- or Include AttributeHelpers # => Add getter/setters, and hash notation access to instance vars of any object.
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 from object created; i.e
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
- - enables serialization by avoiding the use of ''singleton_class'' methods, #attr_accessor, which breaks Serializers:
82
- Serializer supports #to_hash, and standard Marshall''ing. Notice use of #to_hash to convert object back to a Ruby Hash before
83
- using #to_json and #to_xml; presumed to be methods enabled on the standard Ruby Hash class.
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
- person = SknUtils::PageControls.new({name: "Bob"})
86
- person.to_hash # => {"name"=>"Bob"}
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
- ***GenericBean designed to automatically handle the setup for serialization and multi level without arrays
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
- 'obj = SknUtils::ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
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>? and clear_<attr>? method patterns:
104
- 'obj = SknUtils::PageControls.new({name: "Something", phone: "2609998888"})'
105
- 'obj.name?' # => true true or false, like obj.name.present?
106
- 'obj.clear_name' # => nil sets :name to nil
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
- drb = SknUtils::ResultBean.new(params) Basic dot notation: effect of :depth
112
- ---------------------------------------------------- -----------------------------------------------------------------
112
+ == Usage:
113
113
 
114
- (DOES NOT FOLLOW Values) :depth => :single
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
- * params = {one: 1, drb.one = 1
117
- two: { one: 1, drb.two = {one: 1, two: 'two}
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, drb.two = <SknUtils::ResultBean>
142
- two: "two" drb.two.two = 'two'
143
- },
144
- three: [ {one: 'one', two: 2}, drb.three = [<SknUtils::ResultBean>,<SknUtils::ResultBean>]
145
- {three: 'three', four: 4} drb.three[1] = <SknUtils::ResultBean>
146
- ] drb.three[1].four = 4
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
- (DOES NOT FOLLOW Values)
139
+ * Expected usage
153
140
  ```ruby
154
- class SmallPackage < SknUtils::NestedResultBase
155
- def initialize(params={})
156
- super( params.merge({depth: :single}) ) # override default of :multi level
157
- end
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
- (Follow VALUES that are Hashes only.)
153
+
154
+ * Wrap additional methods around the core NestedResult feature set
162
155
  ```ruby
163
- class MyPackage < SknUtils::NestedResultBase
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
- # your other init stuff here
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
- (Follow VALUES that are Hashes and/or Arrays of Hashes, and enable Serializers)
194
- ```ruby
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
- == Build
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
- == Console Workout
201
+
202
+ == Console Workout
237
203
 
238
204
  Start with building gem first.
239
- ```bash
240
- $ cd skn_utils
241
- $ bundle exec pry
242
- [1] pry(main)> require 'active_model'
243
- [2] pry(main)> require 'skn_utils'
244
- [3] pry(main)> rb = SknUtils::ResultBean.new({sample: [{one: "one", two: "two"},{one: 1, two: 2}] })
245
- [4] pry(main)> pg = SknUtils::PageControls.new({sample: [{one: "one", two: "two"},{one: 1, two: 2}] })
246
- [5] pry(main)> pg.sample.first.one # Tip :multi_with_arrays
247
- [6] pry(main)> rb.sample.first.one # Tip :multi without arrays you will get a NoMethodError
248
- [7] pry(main)> rb.sample.first[:one]
249
- ...
250
- [n] pry(main)> exit
251
- * Done
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. See `LICENSE`.
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'skn_utils'
5
+ require 'psych'
6
+
7
+ require 'pry'
8
+ Pry.start
@@ -11,14 +11,14 @@ module SknUtils
11
11
  module_function
12
12
 
13
13
  def option_defaults
14
- @@option_defaults ||= {one: 1, two: 2, three: 3}
14
+ @option_defaults ||= {one: 1, two: 2, three: 3}
15
15
  end
16
16
  def option_defaults=(parms)
17
- @@option_defaults = parms
17
+ @option_defaults = parms
18
18
  end
19
19
 
20
20
  def reset!
21
- @@configuration = Options.new(option_defaults)
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
- @@configuration || reset!
31
- yield(@@configuration) if block_given?
32
- @@configuration
30
+ @configuration || reset!
31
+ yield(@configuration) if block_given?
32
+ @configuration
33
33
  end
34
34
 
35
35
  private