skn_utils 2.0.6 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,382 @@
|
|
1
|
+
##
|
2
|
+
# <project.root>/lib/skn_utils/nested_result.rb
|
3
|
+
#
|
4
|
+
# SknUtils::NestedResult Value Container/Class for Ruby with Indifferent Hash and/or Dot.notation access
|
5
|
+
#
|
6
|
+
# Description:
|
7
|
+
#
|
8
|
+
# Creates an Object with attribute methods for dot.notation and hash.notation access
|
9
|
+
# for each hash input key/value pair.
|
10
|
+
#
|
11
|
+
# If the key's value is an hash itself, it will become an NestedResult Object.
|
12
|
+
# if the key's value is an Array of Hashes, each hash element of the Array will
|
13
|
+
# become an Object; non-hash object are left as-is
|
14
|
+
# if the key's value is an Array of Arrays-of- Hash/Object, each hash element of each Array will
|
15
|
+
# become an Object; non-hash object are left as-is. This array of array of arrays
|
16
|
+
# goes on to the end.
|
17
|
+
#
|
18
|
+
# Transforms entire input hash contents into dot.notation and hash.notation accessible key/value pairs.
|
19
|
+
# - hash
|
20
|
+
# - array of hashes
|
21
|
+
# - non hash element values are not modified,
|
22
|
+
# whether in an array or the basic value in a key/value pair
|
23
|
+
#
|
24
|
+
# The ability of the resulting Object to be YAML/Psych'ed, or Marshaled(dump/load) is preserved
|
25
|
+
#
|
26
|
+
##
|
27
|
+
# Transforms entire input hash contents into dot.notation accessible object
|
28
|
+
# - hash
|
29
|
+
# - array of hashes
|
30
|
+
# - non hash element values are not modified, whether in an array or the basic value in a key/value pair
|
31
|
+
#
|
32
|
+
##
|
33
|
+
# This module provides
|
34
|
+
#
|
35
|
+
# Simple Initialization Pattern
|
36
|
+
# person = SknUtils::NestedResult.new( {name: "Bob", title: {day: 'Analyst', night: 'Fireman'}} )
|
37
|
+
#
|
38
|
+
# Serializers:
|
39
|
+
# person.to_hash
|
40
|
+
# => {name: 'Bob', title: {day: 'Analyst', night: 'Fireman'}}
|
41
|
+
# person.to_json
|
42
|
+
# => "{\"name\":\"Bob\", \"title\":{\"day\":\"Analyst\", \"night\":\"Fireman\"}}"
|
43
|
+
#
|
44
|
+
# Dynamic addition of new key/values after initialization
|
45
|
+
# person.address = 'Fort Wayne Indiana'
|
46
|
+
# person.address
|
47
|
+
# => 'Fort Wayne Indiana'
|
48
|
+
#
|
49
|
+
# dot.notation feature for all instance variables
|
50
|
+
# person.title.day
|
51
|
+
# => "Analyst"
|
52
|
+
# person.name = "James"
|
53
|
+
# => "James"
|
54
|
+
#
|
55
|
+
# InDifferent String/Symbol hash[notation] feature for all instance variables
|
56
|
+
# person['title']['day']
|
57
|
+
# => "Analyst"
|
58
|
+
# person['name'] = "James"
|
59
|
+
# => "James"
|
60
|
+
# person[:name]
|
61
|
+
# => "James"
|
62
|
+
# person[:name] = "Bob"
|
63
|
+
# => "Bob"
|
64
|
+
#
|
65
|
+
# Supports <attr>? predicate method patterns, and delete_field(:attr) method
|
66
|
+
# example:
|
67
|
+
# person.title.night?
|
68
|
+
# => true true or false, like obj.name.present?
|
69
|
+
# person.delete_field(:name) only first/root level attributes can be deleted
|
70
|
+
# => 'Bob' returns last value of deleted key
|
71
|
+
# person.name_not_found
|
72
|
+
# => NoMethodFound raises exception if key is not found
|
73
|
+
#
|
74
|
+
# Exporting hash from any key starting point
|
75
|
+
# person.hash_from(:name)
|
76
|
+
# => {name: 'Bob'} the entire hash tree from that starting point
|
77
|
+
##
|
78
|
+
# Advanced Methods
|
79
|
+
# #to_hash - returns copy of input hash
|
80
|
+
# #to_json(*args) - converts input hash into JSON
|
81
|
+
# #keys - returns the first-level keys of input hash
|
82
|
+
# #delete_field(attr_sym) - removes attribute/key and returns it's former value
|
83
|
+
# #hash_from(starting_attr_sym) - (Protected Method) returns remaining hash starting from key provided
|
84
|
+
#
|
85
|
+
##
|
86
|
+
# Known Issues
|
87
|
+
# - Fixnum keys work as keys with the exception of #respond_to?() which does not support them
|
88
|
+
# - Entries with Fixnums or object-instance keys are accessible only via #[]=(), #[] Hash.notation
|
89
|
+
# methods and not the dot.notation feature
|
90
|
+
#
|
91
|
+
###################################################################################################
|
92
|
+
|
93
|
+
module SknUtils
|
94
|
+
class NestedResult
|
95
|
+
|
96
|
+
def initialize(params={})
|
97
|
+
@container = {}
|
98
|
+
initialize_from_hash(params)
|
99
|
+
end
|
100
|
+
|
101
|
+
def [](attr)
|
102
|
+
container[key_as_sym(attr)]
|
103
|
+
end
|
104
|
+
|
105
|
+
#Feature: if a new attribute is added, on first read method_missing will create getters/setters
|
106
|
+
def []=(attr, value)
|
107
|
+
container.store(key_as_sym(attr), value)
|
108
|
+
end
|
109
|
+
|
110
|
+
def delete_field(name) # protect public methods
|
111
|
+
sym = key_as_sym(name)
|
112
|
+
unless !sym.is_a?(Symbol) || self.class.method_defined?(sym)
|
113
|
+
singleton_class.send(:remove_method, "#{sym.to_s}=".to_sym, sym) rescue nil
|
114
|
+
container.delete(sym)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Exporters
|
120
|
+
#
|
121
|
+
def to_hash
|
122
|
+
attributes
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method :to_h, :to_hash
|
126
|
+
|
127
|
+
def to_json(*args)
|
128
|
+
attributes.to_json(*args)
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Returns a string containing a detailed summary of the keys and values.
|
133
|
+
#
|
134
|
+
InspectKey = :__inspect_key__ # :nodoc:
|
135
|
+
def inspect
|
136
|
+
package = to_hash
|
137
|
+
str = "#<#{self.class}"
|
138
|
+
|
139
|
+
ids = (Thread.current[InspectKey] ||= [])
|
140
|
+
if ids.include?(object_id)
|
141
|
+
return str << ' ...>'
|
142
|
+
end
|
143
|
+
|
144
|
+
ids << object_id
|
145
|
+
begin
|
146
|
+
first = true
|
147
|
+
for k,v in package
|
148
|
+
str << "," unless first
|
149
|
+
first = false
|
150
|
+
str << " #{k}=#{v.inspect}"
|
151
|
+
end
|
152
|
+
return str << '>'
|
153
|
+
ensure
|
154
|
+
ids.pop
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
alias_method :to_s, :inspect
|
159
|
+
|
160
|
+
|
161
|
+
##
|
162
|
+
# Ruby basic Class methods
|
163
|
+
#
|
164
|
+
def ==(other)
|
165
|
+
return false unless other.is_a?(NestedResult)
|
166
|
+
to_hash.eql?(other.to_hash)
|
167
|
+
end
|
168
|
+
alias_method :===, :==
|
169
|
+
|
170
|
+
def eql?(other)
|
171
|
+
return false unless other.is_a?(NestedResult)
|
172
|
+
to_hash.eql?(other.to_hash)
|
173
|
+
end
|
174
|
+
|
175
|
+
def hash
|
176
|
+
to_hash.hash
|
177
|
+
end
|
178
|
+
|
179
|
+
# Feature: returns keys from root input Hash
|
180
|
+
def keys
|
181
|
+
container.keys
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# YAML/Psych load support, chance to re-initialize value methods
|
186
|
+
#
|
187
|
+
# Use our unwrapped/original input Hash when yaml'ing
|
188
|
+
def encode_with(coder)
|
189
|
+
coder['container'] = self.to_h
|
190
|
+
end
|
191
|
+
|
192
|
+
# Use our hash from above to fully re-initialize this instance
|
193
|
+
def init_with(coder)
|
194
|
+
case coder.tag
|
195
|
+
when '!ruby/object:SknUtils::NestedResult'
|
196
|
+
initialize_from_hash( coder.map['container'] )
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
protected
|
201
|
+
|
202
|
+
##
|
203
|
+
# Marshal.load()/.dump() support, chance to re-initialize value methods
|
204
|
+
#
|
205
|
+
def marshal_dump
|
206
|
+
to_hash
|
207
|
+
end
|
208
|
+
|
209
|
+
# Using the String from above create and return an instance of this class
|
210
|
+
def marshal_load(hash)
|
211
|
+
initialize_from_hash(hash)
|
212
|
+
end
|
213
|
+
|
214
|
+
def respond_to_missing?(method, incl_private=false)
|
215
|
+
method_nsym = method.is_a?(Symbol) ? method.to_s[0..-2].to_sym : method
|
216
|
+
container[key_as_sym(method)] || container[method_nsym] || super
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
# Feature: attribute must exist and have a non-blank value to cause this method to return true
|
222
|
+
def attribute?(attr)
|
223
|
+
return false unless container.key?(key_as_sym(attr))
|
224
|
+
![ "", " ", nil, [],[""], [" "], NestedResult.new({}), [[]]].any? {|a| a == container[key_as_sym(attr)] }
|
225
|
+
end
|
226
|
+
|
227
|
+
# Feature: returns a hash of all attributes and their current values
|
228
|
+
def attributes
|
229
|
+
hash_from(container)
|
230
|
+
end
|
231
|
+
|
232
|
+
def container
|
233
|
+
@container ||= {}
|
234
|
+
end
|
235
|
+
|
236
|
+
# returns hash from any root key starting point: object.root_key
|
237
|
+
# - protected to reasonably ensure key is a symbol
|
238
|
+
def hash_from(sym)
|
239
|
+
starting_sym = key_as_sym(sym)
|
240
|
+
bundle = starting_sym == container ? container : { starting_sym => container[starting_sym] }
|
241
|
+
bundle.keys.each_with_object({}) do |attr,collector|
|
242
|
+
value = bundle[attr]
|
243
|
+
case value
|
244
|
+
when Array
|
245
|
+
value = value.map {|ele| array_to_hash(ele) }
|
246
|
+
when NestedResult
|
247
|
+
value = value.to_hash
|
248
|
+
end
|
249
|
+
collector[attr] = value # new copy
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
# Feature: enables dot.notation and creates matching getter/setters
|
254
|
+
def enable_dot_notation(sym)
|
255
|
+
name = key_as_sym(sym)
|
256
|
+
unless !name.is_a?(Symbol) || singleton_class.method_defined?(name)
|
257
|
+
singleton_class.send(:define_method, name) do
|
258
|
+
container[name]
|
259
|
+
end
|
260
|
+
|
261
|
+
singleton_class.send(:define_method, "#{name.to_s}=".to_sym) do |x|
|
262
|
+
container[name] = x
|
263
|
+
end
|
264
|
+
end
|
265
|
+
name
|
266
|
+
end
|
267
|
+
|
268
|
+
def initialize_from_hash(hash)
|
269
|
+
hash.each_pair do |k,v|
|
270
|
+
key = key_as_sym(k)
|
271
|
+
enable_dot_notation(key)
|
272
|
+
case v
|
273
|
+
when Array
|
274
|
+
value = v.map { |element| translate_value(element) }
|
275
|
+
container.store(key, value)
|
276
|
+
when Hash
|
277
|
+
container.store(key, NestedResult.new(v))
|
278
|
+
else
|
279
|
+
container.store(key, v)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Feature: unwrap array of array-of-hashes/object
|
285
|
+
def array_to_hash(array)
|
286
|
+
case array
|
287
|
+
when Array
|
288
|
+
array.map { |element| array_to_hash(element) }
|
289
|
+
when NestedResult
|
290
|
+
array.to_hash
|
291
|
+
else
|
292
|
+
array
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# Feature: wrap array of array-of-hashes/object
|
297
|
+
def translate_value(value)
|
298
|
+
case value
|
299
|
+
when Array
|
300
|
+
value.map { |element| translate_value(element) }
|
301
|
+
when Hash
|
302
|
+
NestedResult.new(value)
|
303
|
+
else
|
304
|
+
value
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def key_as_sym(key)
|
309
|
+
case key
|
310
|
+
when Symbol
|
311
|
+
key
|
312
|
+
when String
|
313
|
+
key.to_sym
|
314
|
+
else
|
315
|
+
key # no change, allows Fixnum and Object instances
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# Feature: post-assign key/value pair, <attr>?? predicate, create getter/setter on first access
|
320
|
+
def method_missing(method, *args, &block)
|
321
|
+
method_sym = key_as_sym(method)
|
322
|
+
method_nsym = method_sym.is_a?(Symbol) ? method.to_s[0..-2].to_sym : method
|
323
|
+
|
324
|
+
|
325
|
+
if method.to_s.end_with?("=") and container[method_nsym].nil? # add new key/value pair, transform value if Hash or Array
|
326
|
+
initialize_from_hash({method_nsym => args.first})
|
327
|
+
|
328
|
+
elsif container.key?(method_sym)
|
329
|
+
puts "#{__method__}() method: #{method}"
|
330
|
+
enable_dot_notation(method_sym) # Add Reader/Writer one first need
|
331
|
+
container[method_sym]
|
332
|
+
|
333
|
+
elsif method.to_s.end_with?('?') # order of tests is significant,
|
334
|
+
attribute?(method_nsym)
|
335
|
+
|
336
|
+
else
|
337
|
+
e = NoMethodError.new "undefined method `#{method}' for #{self.class.name}", method, args
|
338
|
+
e.set_backtrace caller(1)
|
339
|
+
raise e
|
340
|
+
|
341
|
+
end
|
342
|
+
end # end method_missing: errors from enable_dot..., initialize_hash..., and attribute? are possible
|
343
|
+
|
344
|
+
end # end class
|
345
|
+
end # end module
|
346
|
+
|
347
|
+
|
348
|
+
# YAML.load(str) will trigger #init_with for each type it encounters when loading
|
349
|
+
# Psych.dump ==> "--- !ruby/object:SknUtils::NestedResult\ncontainer:\n :one: 1\n :two: two\n"
|
350
|
+
#
|
351
|
+
#
|
352
|
+
# [2] pry(main)> ay = Psych.dump a
|
353
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
354
|
+
# => "--- !ruby/object:SknUtils::NestedResult\ncontainer:\n :one: 1\n :two: two\n"
|
355
|
+
# [3] pry(main)> az = Psych.load ay
|
356
|
+
# respond_to_missing?() checking for method: :init_with existence.
|
357
|
+
# respond_to_missing?() checking for method: :yaml_initialize existence.
|
358
|
+
# => #<SknUtils::NestedResult:0x007fe410993238 @container={:one=>1, :two=>"two"}>
|
359
|
+
|
360
|
+
|
361
|
+
# YAML RTM? querys
|
362
|
+
# [:encode_with, :init_with].include?(method)
|
363
|
+
|
364
|
+
|
365
|
+
# can be accessed just like a hash
|
366
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
367
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
368
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
369
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
370
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
371
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
372
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
373
|
+
# respond_to_missing?() checking for method: :encode_with existence.
|
374
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:seven=>7, :eight=>"eight"}.
|
375
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:four=>4, :five=>5, :six=>#<SknUtils::NestedResult:0x007fba101740e0 @container={:seven=>7, :eight=>"eight"}>, :seven=>false}.
|
376
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:any_key=>#<Tuple:0x007fba101643e8 @first="foo", @second="bar">}.
|
377
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:seven=>7, :eight=>"eight"}.
|
378
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:four=>4, :five=>5, :six=>#<SknUtils::NestedResult:0x007fba1014f880 @container={:seven=>7, :eight=>"eight"}>}.
|
379
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:nine=>9, :ten=>"ten"}.
|
380
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:four=>4, :five=>5, :six=>#<SknUtils::NestedResult:0x007fba1014cd60 @container={:nine=>9, :ten=>"ten"}>}.
|
381
|
+
# init_with() hooking into Yaml/Psych.load for codes: {:one=>"one", :two=>"two", :three=>#<SknUtils::NestedResult:0x007fba10175058 @container={:four=>4, :five=>5, :six=>#<SknUtils::NestedResult:0x007fba101740e0 @container={:seven=>7, :eight=>"eight"}>, :seven=>false}>, :four=>#<SknUtils::NestedResult:0x007fba101664b8 @container={:any_key=>#<Tuple:0x007fba101643e8 @first="foo", @second="bar">}>, :five=>[4, 5, 6], :six=>[#<SknUtils::NestedResult:0x007fba10154628 @container={:four=>4, :five=>5, :six=>#<SknUtils::NestedResult:0x007fba1014f880 @container={:seven=>7, :eight=>"eight"}>}>, #<SknUtils::NestedResult:0x007fba1014d738 @container={:four=>4, :five=>5, :six=>#<SknUtils::NestedResult:0x007fba1014cd60 @container={:nine=>9, :ten=>"ten"}>}>, #<Tuple:0x007fba10146d48 @first="another", @second="tuple">], :seven=>#<Tuple:0x007fba10145a60 @first="hello", @second="world">}.
|
382
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#
|
2
|
+
#
|
3
|
+
# Ruby Notify like class
|
4
|
+
#
|
5
|
+
# Ref: https://ozone.wordpress.com/category/programming/metaprogramming/
|
6
|
+
|
7
|
+
|
8
|
+
class NotifierBase
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@listeners = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def register_listener(l)
|
15
|
+
@listeners.push(l) unless @listeners.include?(l)
|
16
|
+
end
|
17
|
+
|
18
|
+
def unregister_listener(l)
|
19
|
+
@listeners.delete(l)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.attribute(*properties)
|
23
|
+
properties.each do |prop|
|
24
|
+
define_method(prop) {
|
25
|
+
instance_variable_get("@#{prop}")
|
26
|
+
}
|
27
|
+
define_method("#{prop}=") do |value|
|
28
|
+
old_value = instance_variable_get("@#{prop}")
|
29
|
+
return if (value == old_value)
|
30
|
+
@listeners.each { |listener|
|
31
|
+
listener.attribute_changed(prop, old_value, value)
|
32
|
+
}
|
33
|
+
instance_variable_set("@#{prop}", value)
|
34
|
+
end
|
35
|
+
end # loop on properties
|
36
|
+
end # end of attribute method
|
37
|
+
|
38
|
+
end # end of NotifierBase class
|
39
|
+
|
40
|
+
|
41
|
+
# Create a bean from that base
|
42
|
+
class TestBean < NotifierBase
|
43
|
+
attribute :name, :firstname
|
44
|
+
end
|
45
|
+
|
46
|
+
class LoggingPropertyChangeListener
|
47
|
+
def attribute_changed(attribute, old_value, new_value)
|
48
|
+
print attribute, " changed from ",
|
49
|
+
old_value, " to ",
|
50
|
+
new_value, "\n"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class SimpleBean < NotifierBase
|
55
|
+
attribute :name, :firstname
|
56
|
+
|
57
|
+
def impotent_name=(new_name)
|
58
|
+
@name = new_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
test = TestBean.new
|
64
|
+
listener = LoggingPropertyChangeListener.new
|
65
|
+
test.register_listener(listener)
|
66
|
+
test.name = 'James Scott'
|
67
|
+
test.firstname = "Scott"
|
68
|
+
test.firstname = "James"
|
69
|
+
test.unregister_listener(listener)
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
test = SimpleBean.new
|
74
|
+
listener = LoggingPropertyChangeListener.new
|
75
|
+
test.register_listener(listener)
|
76
|
+
test.name = 'James Scott'
|
77
|
+
test.firstname = 'Scott'
|
78
|
+
test.firstname = 'James'
|
79
|
+
test.unregister_listener(listener)
|
80
|
+
|
81
|
+
|
82
|
+
# output it generates:
|
83
|
+
|
84
|
+
# ==> name changed from nil to James Scott
|
85
|
+
# ==> firstname changed from nil to Scott
|
86
|
+
# ==> firstname changed from Scott to James
|
87
|
+
|
88
|
+
|
89
|
+
#
|
90
|
+
# END
|
91
|
+
#
|
92
|
+
|
93
|
+
|
94
|
+
|
data/lib/skn_utils/version.rb
CHANGED
data/lib/skn_utils.rb
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
require "skn_utils/version"
|
2
|
-
require 'skn_utils/
|
3
|
-
require 'skn_utils/nested_result_base'
|
4
|
-
require 'skn_utils/generic_bean'
|
5
|
-
require 'skn_utils/page_controls'
|
6
|
-
require 'skn_utils/result_bean'
|
7
|
-
require 'skn_utils/value_bean'
|
2
|
+
require 'skn_utils/nested_result'
|
8
3
|
require 'skn_utils/null_object'
|
9
4
|
require 'skn_utils/exploring/commander'
|
10
5
|
require 'skn_utils/exploring/action_service'
|
data/skn_utils.gemspec
CHANGED
@@ -9,28 +9,11 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.author = 'James Scott Jr'
|
10
10
|
spec.email = 'skoona@gmail.com'
|
11
11
|
spec.summary = <<EOF
|
12
|
-
Ruby
|
13
|
-
|
14
|
-
|
15
|
-
ResultBean is a PORO (Plain Old Ruby Object) which inherits from NestedResultBean class (inlcuded). This class
|
16
|
-
is instantiated via a hash at Ruby Runtime, allowing access to vars via dot or hash notation,
|
17
|
-
and is serializable (<obj>.to_hash) using standard Hash serialization methods.
|
12
|
+
SknUtils contains a small collection of Ruby utilities, the first being a NestedResult a key/value container.
|
18
13
|
EOF
|
19
14
|
|
20
15
|
spec.description = <<EOF
|
21
|
-
|
22
|
-
If a key's value is also a hash, it too can optionally become an Object.
|
23
|
-
If a key's value is a Array of Hashes, each element of the Array can optionally become an Object.
|
24
|
-
|
25
|
-
|
26
|
-
This nesting action is controlled by the value of the options key ':depth'. Options key :depth defaults
|
27
|
-
to :multi, and has options of :single, :multi, or :multi_with_arrays
|
28
|
-
|
29
|
-
|
30
|
-
The ability of the resulting Object to be Marshalled(dump/load) can be preserved by merging configuration options
|
31
|
-
into the input params. Key ':enable_serialization' set to true. It defaults to false for speed purposes.
|
32
|
-
|
33
|
-
|
16
|
+
The intent of NestedResult class 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).
|
34
17
|
Review the RSpec tests, and or review the README for more details.
|
35
18
|
EOF
|
36
19
|
|
@@ -46,7 +29,8 @@ EOF
|
|
46
29
|
spec.add_development_dependency "rake", ">= 0"
|
47
30
|
spec.add_development_dependency "rspec", '~> 3.0'
|
48
31
|
spec.add_development_dependency "pry", ">= 0"
|
49
|
-
|
32
|
+
spec.add_development_dependency "simplecov", ">= 0"
|
33
|
+
|
50
34
|
## Make sure you can build the gem on older versions of RubyGems too:
|
51
35
|
spec.rubygems_version = "1.6.2"
|
52
36
|
spec.required_rubygems_version = Gem::Requirement.new(">= 0") if spec.respond_to? :required_rubygems_version=
|