skn_utils 1.5.1 → 2.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/README.md +59 -34
- data/README.rdoc +46 -20
- data/lib/skn_utils/attribute_helpers.rb +19 -4
- data/lib/skn_utils/generic_bean.rb +1 -1
- data/lib/skn_utils/nested_result_base.rb +2 -126
- data/lib/skn_utils/page_controls.rb +1 -1
- data/lib/skn_utils/result_bean.rb +1 -1
- data/lib/skn_utils/version.rb +1 -1
- data/lib/skn_utils.rb +0 -1
- data/skn_utils.gemspec +2 -4
- data/spec/lib/skn_utils/generic_bean_spec.rb +4 -2
- data/spec/lib/skn_utils/page_controls_spec.rb +2 -2
- data/spec/lib/skn_utils/result_bean_spec.rb +3 -3
- data/spec/spec_helper.rb +0 -1
- data/spec/support/shared_example_marshalable_ruby_pojo.rb +7 -8
- data/spec/support/shared_example_ruby_pojo.rb +13 -19
- metadata +6 -22
- data/lib/skn_utils/result_bean_with_errors.rb +0 -47
- data/spec/lib/skn_utils/result_bean_with_errors_spec.rb +0 -178
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b02d56671c1ac0e5d4c4a8a4ef3f1230e6a9c95d
|
4
|
+
data.tar.gz: cc4f574c4a2144d228ae9c20f94740bbd56d0aab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92fbdfc68499e85a69999ab153dc949515403e639c9fe042c09e84126f13b23b82517b2dc1c0a20d7b67011c921f8bd114821afbbc791e4e15d40939cd7a24b1
|
7
|
+
data.tar.gz: 104430999272da34e5b7474cee5c1158152a98ebaf18f5d1b4843f237c9dec48a901c7af724ded42f62d30657ee58b77dd0ed2e431851aa4422d8ec846575026
|
data/README.md
CHANGED
@@ -6,17 +6,25 @@ an Object with instance variables and associated getters and setters for Dot or
|
|
6
6
|
instance variables can be added post-create by 'obj.my_new_var = "some value"', or simply assigning it.
|
7
7
|
|
8
8
|
|
9
|
-
The intent of this gem is to be a container of data results, with easy access to its contents with on-demand transformation to hash
|
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.
|
10
11
|
|
11
12
|
* If the key's value is also a hash, it too can optionally become an Object.
|
12
13
|
* if the key's value is a Array of Hashes, each element of the Array can optionally become an Object.
|
13
14
|
|
14
15
|
This nesting action is controlled by the value of the options key ':depth'.
|
15
|
-
The key :depth defaults to :multi,
|
16
|
+
The key :depth defaults to :multi, and has options of :single, :multi, or :multi_with_arrays
|
16
17
|
|
17
18
|
The ability of the resulting Object to be Marshalled(dump/load) can be preserved by merging configuration options
|
18
19
|
into the input params key ':enable_serialization' set to true. It defaults to false for speed purposes
|
19
|
-
|
20
|
+
|
21
|
+
|
22
|
+
### New Features
|
23
|
+
--------------------------------
|
24
|
+
12/2015 V2.0 All references to ActiveRecord or Rails has been removed to allow use in non-Rails environments
|
25
|
+
as a result serialization is done with standard Ruby Hash serialization methods; by first transforming
|
26
|
+
object back to a hash using its #to_hash method.
|
27
|
+
|
20
28
|
|
21
29
|
### Configuration Options
|
22
30
|
--------------------------------
|
@@ -24,6 +32,24 @@ The intent of this gem is to be a container of data results, with easy access to
|
|
24
32
|
:enable_serialization = false -- [ true | false ], for speed, omits creation of attr_accessor
|
25
33
|
:depth = :multi -- [ :single | :multi | :multi_with_arrays ]
|
26
34
|
|
35
|
+
|
36
|
+
### Public Methods
|
37
|
+
--------------------------------
|
38
|
+
|
39
|
+
Each concrete Class supports the following utility methods:
|
40
|
+
#depth_level -- returns parsing depth level, see :depth
|
41
|
+
#serialization_required? -- returns true/false if serialization is enabled
|
42
|
+
#to_hash -- returns a hash of all user attributes
|
43
|
+
#to_hash(true) -- returns a hash of all user and internal attributes
|
44
|
+
#[] -- returns value of attr, when #[<attr_name_symbol>]
|
45
|
+
#[]=(attr, value) -- assigns value to existing attr, or creates a new key/value pair
|
46
|
+
#clear_<attr> -- assigns nil to existing attr, when #clear_attr
|
47
|
+
#<attr>? -- detects true/false presence? of attr, and non-blank existance of attr's value; when #address?
|
48
|
+
#<attr> -- returns value of named attribute
|
49
|
+
#<attr> = (value) -- assigns value to existing attr, or creates a new key/value pair
|
50
|
+
-- Where <attr> is a key value from the initial hash, or a key that was dynamically added
|
51
|
+
|
52
|
+
|
27
53
|
### Public Components
|
28
54
|
--------------------------------
|
29
55
|
|
@@ -31,34 +57,32 @@ The intent of this gem is to be a container of data results, with easy access to
|
|
31
57
|
SknUtils::GenericBean # => Serializable, includes attr_accessors, and follows hash values only.
|
32
58
|
SknUtils::PageControls # => Serializable, includes attr_accessors, and follows hash values and arrays of hashes.
|
33
59
|
SknUtils::ResultBean # => Not Serializable, includes attr_accessors, and follows hash values only.
|
34
|
-
SknUtils::ResultsBeanWithErrors # => Same as ResultBean with addition of ActiveModel::Errors object.
|
35
60
|
or Include AttributeHelpers # => Add getter/setters, and hash notation access to instance vars of any object.
|
36
61
|
|
37
62
|
|
38
63
|
## Basic features include:
|
39
64
|
```ruby
|
40
65
|
- provides the hash or dot notation methods of accessing values from object created; i.e
|
41
|
-
'obj = ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
66
|
+
'obj = SknUtils::ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
42
67
|
'x = obj.value1' or 'x = obj.value2.one'
|
43
68
|
'x = obj["value1"]'
|
44
69
|
'x = obj[:value1]'
|
45
70
|
|
46
71
|
- enables serialization by avoiding the use of ''singleton_class'' methods which breaks Serializers:
|
47
|
-
Serializer supports
|
72
|
+
Serializer supports #to_hash, and standard Marshall''ing. Notice use of #to_hash to convert object back to a Ruby Hash before
|
73
|
+
using #to_json and #to_xml; presumed to be methods enabled on the standard Ruby Hash class.
|
48
74
|
|
49
|
-
person = PageControls.new({name: "Bob"})
|
50
|
-
person.attributes # => {"name"=>"Bob"}
|
51
|
-
person.serializable_hash # => {"name"=>"Bob"}
|
75
|
+
person = SknUtils::PageControls.new({name: "Bob"})
|
52
76
|
person.to_hash # => {"name"=>"Bob"}
|
53
|
-
person.to_json
|
54
|
-
person.to_xml
|
77
|
+
person.to_hash.to_json # => "{\"name\":\"Bob\"}"
|
78
|
+
person.to_hash.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<page-controls>\n <name>Bob</name>\n</page-controls>\n"
|
55
79
|
dmp = Marshal.dump(person) # => "\x04\bo:\x1ASknUtils::PageControls\x06:\n@nameI\"\bBob\x06:\x06ET"
|
56
80
|
person = Marshal.load(dmp) # => #<SknUtils::PageControls:0x007faede906d40 @name="Bob">
|
57
81
|
|
58
|
-
***GenericBean designed to automatically
|
82
|
+
***GenericBean designed to automatically handles the setup for serialization and multi level without arrays
|
59
83
|
|
60
84
|
- post create additions:
|
61
|
-
'obj = ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
85
|
+
'obj = SknUtils::ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
62
86
|
'x = obj.one' --causes NoMethodError
|
63
87
|
'x = obj.one = 'some other value' --creates a new instance value with accessors
|
64
88
|
'x = obj.one = {key1: 1, two: "two"}' --creates a new ***bean as the value of obj.one
|
@@ -67,17 +91,17 @@ The intent of this gem is to be a container of data results, with easy access to
|
|
67
91
|
'y = obj.one['two'] --returns "two"
|
68
92
|
|
69
93
|
- supports predicates <attr>? and clear_<attr>? method patterns:
|
70
|
-
'obj = PageControls.new({name: "Something", phone: "2609998888"})'
|
94
|
+
'obj = SknUtils::PageControls.new({name: "Something", phone: "2609998888"})'
|
71
95
|
'obj.name?' # => true true or false, like obj.name.present?
|
72
96
|
'obj.clear_name' # => nil sets :name to nil
|
73
97
|
```
|
74
98
|
|
75
|
-
The combination of this NestedResultBase(dot notation class) and AttributeHelpers(hash notation module), produces
|
99
|
+
The combination of this NestedResultBase(dot notation class) and AttributeHelpers(hash notation module), produces these effects given the same params hash:
|
76
100
|
|
77
|
-
SknUtils::ResultBean.new(params) Basic dot notation: effect of :depth
|
101
|
+
drb = SknUtils::ResultBean.new(params) Basic dot notation: effect of :depth
|
78
102
|
---------------------------------------------------- -----------------------------------------------------------------
|
79
103
|
|
80
|
-
(DOES NOT FOLLOW Values)
|
104
|
+
(DOES NOT FOLLOW Values) ***:depth => :single
|
81
105
|
```ruby
|
82
106
|
* params = {one: 1, drb.one = 1
|
83
107
|
two: { one: 1, drb.two = {one: 1, two: 'two}
|
@@ -89,11 +113,11 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
89
113
|
}
|
90
114
|
```
|
91
115
|
|
92
|
-
(Follow VALUES that are Hashes only.)
|
116
|
+
(Follow VALUES that are Hashes only.) ***:depth => :multi
|
93
117
|
```ruby
|
94
118
|
* params = {one: 1, drb.one = 1
|
95
119
|
two: { one: 1, drb.two = <SknUtils::ResultBean>
|
96
|
-
|
120
|
+
two: "two" drb.two.two = 'two'
|
97
121
|
},
|
98
122
|
three: [ {one: 'one', two: 2}, drb.three = [{one: 'one', two: 2},{three: 'three', four: 4}]
|
99
123
|
{three: 'three', four: 4} drb.three[1] = {three: 'three', four: 4}
|
@@ -101,14 +125,14 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
101
125
|
}
|
102
126
|
```
|
103
127
|
|
104
|
-
(Follow VALUES that are Hashes and/or Arrays of Hashes)
|
128
|
+
(Follow VALUES that are Hashes and/or Arrays of Hashes) ***:depth => :multi_with_arrays
|
105
129
|
```ruby
|
106
130
|
* params = {one: 1, drb.one = 1
|
107
131
|
two: { one: 1, drb.two = <SknUtils::ResultBean>
|
108
132
|
two: "two" drb.two.two = 'two'
|
109
133
|
},
|
110
134
|
three: [ {one: 'one', two: 2}, drb.three = [<SknUtils::ResultBean>,<SknUtils::ResultBean>]
|
111
|
-
{three: 'three', four: 4}
|
135
|
+
{three: 'three', four: 4} drb.three[1] = <SknUtils::ResultBean>
|
112
136
|
] drb.three[1].four = 4
|
113
137
|
}
|
114
138
|
|
@@ -126,13 +150,13 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
126
150
|
|
127
151
|
(Follow VALUES that are Hashes only.)
|
128
152
|
```ruby
|
129
|
-
class
|
153
|
+
class MyPackage < SknUtils::NestedResultBase
|
130
154
|
# defaults to :multi level
|
131
155
|
end
|
132
156
|
|
133
157
|
-- or --
|
134
158
|
|
135
|
-
class
|
159
|
+
class MyPackage < SknUtils::NestedResultBase
|
136
160
|
def initialize(params={})
|
137
161
|
# your other init stuff here
|
138
162
|
super(params) # default taken
|
@@ -141,7 +165,7 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
141
165
|
|
142
166
|
-- or --
|
143
167
|
|
144
|
-
class
|
168
|
+
class MyPackage < SknUtils::NestedResultBase
|
145
169
|
def initialize(params={})
|
146
170
|
# your other init stuff here
|
147
171
|
super( params.merge({depth: :multi}) ) # Specified
|
@@ -149,7 +173,7 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
149
173
|
end
|
150
174
|
|
151
175
|
** - or -- enable serialization and default to multi
|
152
|
-
class
|
176
|
+
class MyPackage < SknUtils::NestedResultBase
|
153
177
|
def initialize(params={})
|
154
178
|
super( params.merge({enable_serialization: true}) ) # Specified with Serialization Enabled
|
155
179
|
end
|
@@ -158,7 +182,7 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
158
182
|
|
159
183
|
(Follow VALUES that are Hashes and/or Arrays of Hashes, and enable Serializers)
|
160
184
|
```ruby
|
161
|
-
class
|
185
|
+
class MyPackage < SknUtils::NestedResultBase
|
162
186
|
def initialize(params={})
|
163
187
|
super( params.merge({depth: :multi_with_arrays, enable_serialization: true}) ) # override defaults
|
164
188
|
end
|
@@ -171,7 +195,9 @@ Use GenericBean or PageControls if serialization is needed, they initialize with
|
|
171
195
|
|
172
196
|
## Installation
|
173
197
|
----------------
|
174
|
-
runtime prereqs:
|
198
|
+
runtime prereqs:
|
199
|
+
V2+ None
|
200
|
+
V1+ gem 'active_model', '~> 3.0'
|
175
201
|
|
176
202
|
Add this line to your application's Gemfile:
|
177
203
|
|
@@ -204,13 +230,12 @@ Start with building gem first.
|
|
204
230
|
```bash
|
205
231
|
$ cd skn_utils
|
206
232
|
$ bundle exec pry
|
207
|
-
[1] pry(main)> require '
|
208
|
-
[2] pry(main)>
|
209
|
-
[3] pry(main)>
|
210
|
-
[4] pry(main)> pg
|
211
|
-
[5] pry(main)>
|
212
|
-
[6] pry(main)> rb.sample.first
|
213
|
-
[7] pry(main)> rb.sample.first[:one]
|
233
|
+
[1] pry(main)> require 'skn_utils'
|
234
|
+
[2] pry(main)> rb = SknUtils::ResultBean.new({sample: [{one: "one", two: "two"},{one: 1, two: 2}] })
|
235
|
+
[3] pry(main)> pg = SknUtils::PageControls.new({sample: [{one: "one", two: "two"},{one: 1, two: 2}] })
|
236
|
+
[4] pry(main)> pg.sample.first.one # Tip :multi_with_arrays
|
237
|
+
[5] pry(main)> rb.sample.first.one # Tip :multi without arrays you will get a NoMethodError
|
238
|
+
[6] pry(main)> rb.sample.first[:one]
|
214
239
|
|
215
240
|
[n] pry(main)> exit
|
216
241
|
* Done
|
data/README.rdoc
CHANGED
@@ -6,24 +6,50 @@ an Object with instance variables and associated getters and setters for Dot or
|
|
6
6
|
instance variables can be added post-create by 'obj.my_new_var = "some value"', or simply assigning it.
|
7
7
|
|
8
8
|
|
9
|
-
The intent of this gem is to be a container of data results, with easy access to its contents with on-demand transformation to hash
|
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.
|
10
11
|
|
11
12
|
* If the key's value is also a hash, it too can optionally become an Object.
|
12
13
|
* if the key's value is a Array of Hashes, each element of the Array can optionally become an Object.
|
13
14
|
|
14
15
|
This nesting action is controlled by the value of the options key ':depth'.
|
15
|
-
The key :depth defaults to :multi,
|
16
|
+
The key :depth defaults to :multi, and has options of :single, :multi, or :multi_with_arrays
|
16
17
|
|
17
18
|
The ability of the resulting Object to be Marshalled(dump/load) can be preserved by merging configuration options
|
18
19
|
into the input params key ':enable_serialization' set to true. It defaults to false for speed purposes
|
19
20
|
|
20
21
|
|
22
|
+
=== New Features
|
23
|
+
--------------------------------
|
24
|
+
12/2015 V2.0 All references to ActiveRecord or Rails has been removed to allow use in non-Rails environments
|
25
|
+
as a result serialization is done with standard Ruby Hash serialization methods; by first transforming
|
26
|
+
object back to a hash using its #to_hash method.
|
27
|
+
|
28
|
+
|
21
29
|
=== Configuration Options
|
22
30
|
--------------------------------
|
23
31
|
|
24
32
|
:enable_serialization = false -- [ true | false ], for speed, omits creation of attr_accessor
|
25
33
|
:depth = :multi -- [ :single | :multi | :multi_with_arrays ]
|
26
34
|
|
35
|
+
|
36
|
+
=== Public Methods
|
37
|
+
--------------------------------
|
38
|
+
|
39
|
+
Each concrete Class supports the following utility methods:
|
40
|
+
#depth_level -- returns parsing depth level, see :depth
|
41
|
+
#serialization_required? -- returns true/false if serialization is enabled
|
42
|
+
#to_hash -- returns a hash of all user attributes
|
43
|
+
#to_hash(true) -- returns a hash of all user and internal attributes
|
44
|
+
#[] -- returns value of attr, when #[<attr_name_symbol>]
|
45
|
+
#[]=(attr, value) -- assigns value to existing attr, or creates a new key/value pair
|
46
|
+
#clear_<attr> -- assigns nil to existing attr, when #clear_attr
|
47
|
+
#<attr>? -- detects true/false presence? of attr, and non-blank existance of attr's value; when #address?
|
48
|
+
#<attr> -- returns value of named attribute
|
49
|
+
#<attr> = (value) -- assigns value to existing attr, or creates a new key/value pair
|
50
|
+
-- Where <attr> is a key value from the initial hash, or a key that was dynamically added
|
51
|
+
|
52
|
+
|
27
53
|
=== Public Components
|
28
54
|
--------------------------------
|
29
55
|
|
@@ -31,34 +57,32 @@ The intent of this gem is to be a container of data results, with easy access to
|
|
31
57
|
SknUtils::GenericBean # => Serializable, includes attr_accessors, and follows hash values only.
|
32
58
|
SknUtils::PageControls # => Serializable, includes attr_accessors, and follows hash values and arrays of hashes.
|
33
59
|
SknUtils::ResultBean # => Not Serializable, includes attr_accessors, and follows hash values only.
|
34
|
-
SknUtils::ResultsBeanWithErrors # => Same as ResultBean with addition of ActiveModel::Errors object.
|
35
60
|
or Include AttributeHelpers # => Add getter/setters, and hash notation access to instance vars of any object.
|
36
61
|
|
37
62
|
|
38
63
|
== Basic features include:
|
39
64
|
```ruby
|
40
65
|
- provides the hash or dot notation methods of accessing values from object created; i.e
|
41
|
-
'obj = ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
66
|
+
'obj = SknUtils::ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
42
67
|
'x = obj.value1' or 'x = obj.value2.one'
|
43
68
|
'x = obj["value1"]'
|
44
69
|
'x = obj[:value1]'
|
45
70
|
|
46
71
|
- enables serialization by avoiding the use of ''singleton_class'' methods which breaks Serializers:
|
47
|
-
Serializer supports
|
72
|
+
Serializer supports #to_hash, and standard Marshall''ing. Notice use of #to_hash to convert object back to a Ruby Hash before
|
73
|
+
using #to_json and #to_xml; presumed to be methods enabled on the standard Ruby Hash class.
|
48
74
|
|
49
|
-
person = PageControls.new({name: "Bob"})
|
50
|
-
person.attributes # => {"name"=>"Bob"}
|
51
|
-
person.serializable_hash # => {"name"=>"Bob"}
|
75
|
+
person = SknUtils::PageControls.new({name: "Bob"})
|
52
76
|
person.to_hash # => {"name"=>"Bob"}
|
53
|
-
person.to_json
|
54
|
-
person.to_xml
|
77
|
+
person.to_hash.to_json # => "{\"name\":\"Bob\"}"
|
78
|
+
person.to_hash.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<page-controls>\n <name>Bob</name>\n</page-controls>\n"
|
55
79
|
dmp = Marshal.dump(person) # => "\x04\bo:\x1ASknUtils::PageControls\x06:\n@nameI\"\bBob\x06:\x06ET"
|
56
80
|
person = Marshal.load(dmp) # => #<SknUtils::PageControls:0x007faede906d40 @name="Bob">
|
57
81
|
|
58
82
|
***GenericBean designed to automatically handle the setup for serialization and multi level without arrays
|
59
83
|
|
60
84
|
- post create additions:
|
61
|
-
'obj = ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
85
|
+
'obj = SknUtils::ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
62
86
|
'x = obj.one' --causes NoMethodError
|
63
87
|
'x = obj.one = 'some other value' --creates a new instance value with accessors
|
64
88
|
'x = obj.one = {key1: 1, two: "two"}' --creates a new ***bean as the value of obj.one
|
@@ -67,14 +91,14 @@ The intent of this gem is to be a container of data results, with easy access to
|
|
67
91
|
'y = obj.one['two'] --returns "two"
|
68
92
|
|
69
93
|
- supports predicates <attr>? and clear_<attr>? method patterns:
|
70
|
-
'obj = PageControls.new({name: "Something", phone: "2609998888"})'
|
94
|
+
'obj = SknUtils::PageControls.new({name: "Something", phone: "2609998888"})'
|
71
95
|
'obj.name?' # => true true or false, like obj.name.present?
|
72
96
|
'obj.clear_name' # => nil sets :name to nil
|
73
97
|
```
|
74
98
|
|
75
99
|
The combination of this NestedResultBase(dot notation class) and AttributeHelpers(hash notation module), produces this effect given the same params hash:
|
76
100
|
|
77
|
-
SknUtils::ResultBean.new(params) Basic dot notation: effect of :depth
|
101
|
+
drb = SknUtils::ResultBean.new(params) Basic dot notation: effect of :depth
|
78
102
|
---------------------------------------------------- -----------------------------------------------------------------
|
79
103
|
|
80
104
|
(DOES NOT FOLLOW Values) :depth => :single
|
@@ -126,13 +150,13 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
126
150
|
|
127
151
|
(Follow VALUES that are Hashes only.)
|
128
152
|
```ruby
|
129
|
-
class
|
153
|
+
class MyPackage < SknUtils::NestedResultBase
|
130
154
|
# defaults to :multi level
|
131
155
|
end
|
132
156
|
|
133
157
|
-- or --
|
134
158
|
|
135
|
-
class
|
159
|
+
class MyPackage < SknUtils::NestedResultBase
|
136
160
|
def initialize(params={})
|
137
161
|
# your other init stuff here
|
138
162
|
super(params) # default taken
|
@@ -141,7 +165,7 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
141
165
|
|
142
166
|
-- or --
|
143
167
|
|
144
|
-
class
|
168
|
+
class MyPackage < SknUtils::NestedResultBase
|
145
169
|
def initialize(params={})
|
146
170
|
# your other init stuff here
|
147
171
|
super( params.merge({depth: :multi}) ) # Specified
|
@@ -149,7 +173,7 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
149
173
|
end
|
150
174
|
|
151
175
|
** - or -- enable serialization and default to multi
|
152
|
-
class
|
176
|
+
class MyPackage < SknUtils::NestedResultBase
|
153
177
|
def initialize(params={})
|
154
178
|
super( params.merge({enable_serialization: true}) ) # Specified with Serialization Enabled
|
155
179
|
end
|
@@ -158,7 +182,7 @@ The combination of this NestedResultBase(dot notation class) and AttributeHelper
|
|
158
182
|
|
159
183
|
(Follow VALUES that are Hashes and/or Arrays of Hashes, and enable Serializers)
|
160
184
|
```ruby
|
161
|
-
class
|
185
|
+
class MyPackage < SknUtils::NestedResultBase
|
162
186
|
def initialize(params={})
|
163
187
|
super( params.merge({depth: :multi_with_arrays, enable_serialization: true}) ) # override defaults
|
164
188
|
end
|
@@ -171,11 +195,13 @@ Use GenericBean or PageControls if serialization is needed, they initialize with
|
|
171
195
|
|
172
196
|
== Installation
|
173
197
|
----------------
|
174
|
-
runtime prereqs:
|
198
|
+
runtime prereqs:
|
199
|
+
V2+ None
|
200
|
+
V1+ gem 'active_model', '~> 3.0'
|
175
201
|
|
176
202
|
Add this line to your application's Gemfile:
|
177
203
|
|
178
|
-
|
204
|
+
gem 'skn_utils'
|
179
205
|
|
180
206
|
And then execute:
|
181
207
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
##
|
2
|
-
# <
|
2
|
+
# <project.root>/lib/skn_utils/attribute_helpers.rb
|
3
3
|
#
|
4
4
|
# *** See SknUtils::NestedResultBase for details ***
|
5
5
|
#
|
@@ -29,13 +29,28 @@
|
|
29
29
|
module SknUtils
|
30
30
|
module AttributeHelpers
|
31
31
|
|
32
|
+
# These methods normally come from ActiveSupport in Rails
|
33
|
+
# If your not using this gem with Rails, then the :included method
|
34
|
+
# will add these routines to the Object class
|
35
|
+
def self.included(mod)
|
36
|
+
unless Object.respond_to? :instance_variable_names
|
37
|
+
Object.class_exec {
|
38
|
+
def instance_variable_names
|
39
|
+
instance_variables.map { |var| var.to_s }
|
40
|
+
end
|
41
|
+
def instance_values
|
42
|
+
Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
32
48
|
# return a hash of all attributes and their current values
|
33
49
|
# including nested arrays of hashes/objects
|
34
50
|
def attributes(filter_internal=true)
|
35
51
|
instance_variable_names.each_with_object({}) do |attr,collector|
|
36
52
|
next if ['skn_enable_serialization', 'skn_enabled_depth'].include?(attr.to_s[1..-1]) and filter_internal # skip control keys
|
37
53
|
value = instance_variable_get(attr)
|
38
|
-
next if value.is_a?(ActiveModel::Errors)
|
39
54
|
|
40
55
|
if value.kind_of?(Array) and value.first.respond_to?(:attribute_helper_object)
|
41
56
|
value = value.map {|ov| ov.respond_to?(:attribute_helper_object) ? ov.attributes : ov }
|
@@ -46,8 +61,8 @@ module SknUtils
|
|
46
61
|
end
|
47
62
|
end
|
48
63
|
|
49
|
-
def to_hash
|
50
|
-
attributes
|
64
|
+
def to_hash(exclude_internal_vars=false)
|
65
|
+
attributes(!exclude_internal_vars)
|
51
66
|
end
|
52
67
|
|
53
68
|
# An alternative mechanism for property access.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
##
|
2
|
-
# <
|
2
|
+
# <project.root>/lib/skn_utils/nested_result_base.rb
|
3
3
|
#
|
4
4
|
# Creates an Object with instance variables and associated getters and setters for hash each input key.
|
5
5
|
# If the key's value is also a hash itself, it too will become an Object.
|
@@ -9,7 +9,7 @@
|
|
9
9
|
# The key :depth defaults to :multi, an has options of :single, or :multi_with_arrays
|
10
10
|
#
|
11
11
|
# The ability of the resulting Object to be Marshalled(dump/load) can be preserved by merging
|
12
|
-
#
|
12
|
+
# input params key ':enable_serialization' set to true. It defaults to false for speed purposes
|
13
13
|
#
|
14
14
|
##
|
15
15
|
# Operational Options
|
@@ -17,127 +17,6 @@
|
|
17
17
|
# :enable_serialization = false -- [ true | false ], for speed, omits creation of attr_accessor
|
18
18
|
# :depth = :multi -- [ :single | :multi | :multi_with_arrays ]
|
19
19
|
##
|
20
|
-
# Public Components
|
21
|
-
# --------------------------------
|
22
|
-
# Inherit from NestedResultBase
|
23
|
-
# or Include AttributeHelpers
|
24
|
-
##
|
25
|
-
#
|
26
|
-
# Basic function includes:
|
27
|
-
# - provides the hash or dot notation methods of accessing values from object created; i.e
|
28
|
-
# 'obj = ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
29
|
-
# 'x = obj.value1' or 'x = obj.value2.one'
|
30
|
-
# 'x = obj["value1"]'
|
31
|
-
# 'x = obj[:value1]'
|
32
|
-
#
|
33
|
-
# - enables serialization by avoiding the use of 'singleton_class' methods which breaks Serializers
|
34
|
-
# Serializer supports xml, json, hash, and standard Marshall'ing
|
35
|
-
#
|
36
|
-
# person = PageControls.new({name: "Bob"})
|
37
|
-
# person.attributes # => {"name"=>"Bob"}
|
38
|
-
# person.serializable_hash # => {"name"=>"Bob"}
|
39
|
-
# person.to_hash # => {"name"=>"Bob"}
|
40
|
-
# person.to_json # => "{\"name\":\"Bob\"}"
|
41
|
-
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<page-controls>\n <name>Bob</name>\n</page-controls>\n"
|
42
|
-
# dmp = Marshal.dump(person) # => "\x04\bo:\x1ASknUtils::PageControls\x06:\n@nameI\"\bBob\x06:\x06ET"
|
43
|
-
# person = Marshal.load(dmp) # => #<SknUtils::PageControls:0x007faede906d40 @name="Bob">
|
44
|
-
#
|
45
|
-
# ***GenericBean designed to automatically handle the setup for serialization and multi level without arrays
|
46
|
-
#
|
47
|
-
# - post create additions:
|
48
|
-
# 'obj = ResultBean.new({value1: "some value", value2: {one: 1, two: "two"}})
|
49
|
-
# 'x = obj.one' --causes NoMethodError
|
50
|
-
# 'x = obj.one = 'some other value' --creates a new instance value with accessors
|
51
|
-
# 'x = obj.one = {key1: 1, two: "two"}' --creates a new ***bean as the value of obj.one
|
52
|
-
# 'y = obj.one.two' --returns "two"
|
53
|
-
# 'y = obj.one[:two] --returns "two"
|
54
|
-
# 'y = obj.one['two'] --returns "two"
|
55
|
-
#
|
56
|
-
# - supports predicates <attr>? and clear_<attr>? method patterns
|
57
|
-
# 'obj = PageControls.new({name: "Something", phone: "2604815365"})'
|
58
|
-
# 'obj.name?' # => true true or false, like obj.name.present?
|
59
|
-
# 'obj.clear_name' # => nil sets :name to nil
|
60
|
-
#
|
61
|
-
##
|
62
|
-
# The combination of this NestedResultBase(dot notation class) and AttributeHelpers(hash notation module), produces
|
63
|
-
# this effect from an input hash:
|
64
|
-
#
|
65
|
-
# {:depth => <select>, ...} Input Hash Basic dot notation
|
66
|
-
# ------------------------- --------------------------------------- ---------------------------------
|
67
|
-
#
|
68
|
-
## (DOES NOT FOLLOW Values)
|
69
|
-
# * :single - {one: 1, drb.one = 1
|
70
|
-
# two: { one: 1, drb.two = {one: 1, two: 'two}
|
71
|
-
# two: "two" drb.two.two = NoMethodError
|
72
|
-
# },
|
73
|
-
# three: [ {one: 'one', two: 2}, drb.three = [{one: 'one', two: 2},{three: 'three', four: 4}]
|
74
|
-
# {three: 'three', four: 4} drb.three[1] = {three: 'three', four: 4}
|
75
|
-
# ] drb.three[1].four = NoMethodError
|
76
|
-
# }
|
77
|
-
#
|
78
|
-
## (Follow VALUES that are Hashes only.)
|
79
|
-
# * :multi - {one: 1, drb.one = 1
|
80
|
-
# two: { one: 1, drb.two.one = 1
|
81
|
-
# two: "two" drb.two.two = 'two'
|
82
|
-
# },
|
83
|
-
# three: [ {one: 'one', two: 2}, drb.three = [{one: 'one', two: 2},{three: 'three', four: 4}]
|
84
|
-
# {three: 'three', four: 4} drb.three[1] = {three: 'three', four: 4}
|
85
|
-
# ] drb.three[1].four = NoMethodError
|
86
|
-
# }
|
87
|
-
#
|
88
|
-
## (Follow VALUES that are Hashes and/or Arrays of Hashes)
|
89
|
-
# * :multi_with_arrays - {one: 1, drb.one = 1
|
90
|
-
# two: { one: 1, drb.two.one = 1
|
91
|
-
# two: "two" drb.two.two = 'two'
|
92
|
-
# },
|
93
|
-
# three: [ {one: 'one', two: 2}, drb.three.first.one = 'one'
|
94
|
-
# {three: 'three', four: 4} drb.three[1].four = 4
|
95
|
-
# ]
|
96
|
-
# }
|
97
|
-
#
|
98
|
-
##
|
99
|
-
# -- SubClassing Usage Examples --
|
100
|
-
#
|
101
|
-
# (DOES NOT FOLLOW Values)
|
102
|
-
# class SmallPackage < NestedResultBase
|
103
|
-
# def initialize(params={})
|
104
|
-
# super( params.merge({depth: :single}) ) # override default of :multi level
|
105
|
-
# end
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# (Follow VALUES that are Hashes only.)
|
109
|
-
# class ResultBean < NestedResultBase
|
110
|
-
# # defaults to :multi level
|
111
|
-
# end
|
112
|
-
# -- or --
|
113
|
-
# class ResultBean < NestedResultBase
|
114
|
-
# def initialize(params={})
|
115
|
-
# # your other init stuff here
|
116
|
-
# super(params) # default taken
|
117
|
-
# end
|
118
|
-
# end
|
119
|
-
# -- or --
|
120
|
-
# class ResultBean < NestedResultBase
|
121
|
-
# def initialize(params={})
|
122
|
-
# # your other init stuff here
|
123
|
-
# super( params.merge({depth: :multi}) ) # Specified
|
124
|
-
# end
|
125
|
-
# end
|
126
|
-
# ** - or -- enable serialization and default to multi
|
127
|
-
# class GenericBean < NestedResultBase
|
128
|
-
# def initialize(params={})
|
129
|
-
# super( params.merge({enable_serialization: true}) ) # Specified with Serialization Enabled
|
130
|
-
# end
|
131
|
-
# end
|
132
|
-
#
|
133
|
-
# (Follow VALUES that are Hashes and/or Arrays of Hashes, and enable Serializers)
|
134
|
-
# class PageControl < NestedResultBase
|
135
|
-
# def initialize(params={})
|
136
|
-
# super( params.merge({depth: :multi_with_arrays, enable_serialization: true}) ) # override defaults
|
137
|
-
# end
|
138
|
-
# end
|
139
|
-
#
|
140
|
-
##
|
141
20
|
# NOTE: Cannot be Marshalled/Serialized unless input params.merge({enable_serialization: true}) -- default is false
|
142
21
|
# Use GenericBean if serialization is needed, it sets this value to true automatically
|
143
22
|
##
|
@@ -146,9 +25,6 @@
|
|
146
25
|
module SknUtils
|
147
26
|
|
148
27
|
class NestedResultBase
|
149
|
-
include ActiveModel::Serialization
|
150
|
-
include ActiveModel::Serializers::JSON
|
151
|
-
include ActiveModel::Serializers::Xml
|
152
28
|
include AttributeHelpers
|
153
29
|
|
154
30
|
# :depth controls how deep into input hash/arrays we convert
|
data/lib/skn_utils/version.rb
CHANGED
data/lib/skn_utils.rb
CHANGED
data/skn_utils.gemspec
CHANGED
@@ -13,8 +13,8 @@ Ruby convenience utilities, the first being a ResultBean.
|
|
13
13
|
|
14
14
|
|
15
15
|
ResultBean is a PORO (Plain Old Ruby Object) which inherits from NestedResultBean class (inlcuded). This class
|
16
|
-
is
|
17
|
-
and is serializable
|
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.
|
18
18
|
EOF
|
19
19
|
|
20
20
|
spec.description = <<EOF
|
@@ -45,8 +45,6 @@ EOF
|
|
45
45
|
spec.executables = []
|
46
46
|
spec.test_files = spec.files.grep(%r{^(spec)/})
|
47
47
|
spec.require_paths = ["lib"]
|
48
|
-
|
49
|
-
spec.add_runtime_dependency 'activemodel', '>= 3.0'
|
50
48
|
|
51
49
|
spec.add_development_dependency "bundler", ">= 0"
|
52
50
|
spec.add_development_dependency "rake", ">= 0"
|
@@ -22,8 +22,8 @@ RSpec.describe SknUtils::GenericBean, "Generic Marshal'able Bean class " do
|
|
22
22
|
expect { dmp = Marshal.dump(object) }.not_to raise_error
|
23
23
|
expect { obj = Marshal.load(dmp) }.not_to raise_error
|
24
24
|
expect(obj).to be_a(SknUtils::GenericBean)
|
25
|
-
expect(
|
26
|
-
expect(
|
25
|
+
expect(obj.fifty.any_key).to eql "any value"
|
26
|
+
expect(obj.sixty).to eql 60
|
27
27
|
end
|
28
28
|
it "Initializes from a hash" do
|
29
29
|
expect(SknUtils::GenericBean.new({one: "one", two: "two"})).to be
|
@@ -41,6 +41,8 @@ RSpec.describe SknUtils::GenericBean, "Generic Marshal'able Bean class " do
|
|
41
41
|
it "Supports - respond_to? - method, because it has accessors or method_missing coverage" do
|
42
42
|
expect(object).to respond_to(:one)
|
43
43
|
expect(object.one).to eql "one"
|
44
|
+
expect{ object.fifty = {any_key: "any value"} }.not_to raise_error
|
45
|
+
expect( object.fifty).to respond_to(:any_key)
|
44
46
|
end
|
45
47
|
it "nest objects if multi-level hash is given" do
|
46
48
|
expect(object.one).to be_eql("one")
|
@@ -30,8 +30,8 @@ RSpec.describe SknUtils::PageControls, "PageControls Marshal'able Bean class " d
|
|
30
30
|
expect { dmp = Marshal.dump(object) }.not_to raise_error
|
31
31
|
expect { obj = Marshal.load(dmp) }.not_to raise_error
|
32
32
|
expect(obj).to be_a(SknUtils::PageControls)
|
33
|
-
expect(
|
34
|
-
expect(
|
33
|
+
expect( obj.fifty.any_key).to eql "any value"
|
34
|
+
expect( obj.sixty).to eql 60
|
35
35
|
end
|
36
36
|
it "Initializes from a hash" do
|
37
37
|
expect(object).to be
|
@@ -81,9 +81,9 @@ RSpec.describe SknUtils::ResultBean, "Result Bean class - Basic useage." do
|
|
81
81
|
dmp = YAML::dump(object)
|
82
82
|
@obj = YAML::load(dmp)
|
83
83
|
# Restore setters
|
84
|
-
@obj.attributes.keys.each do |k|
|
85
|
-
@obj.singleton_class.send(:attr_accessor, k)
|
86
|
-
end
|
84
|
+
# @obj.attributes.keys.each do |k|
|
85
|
+
# @obj.singleton_class.send(:attr_accessor, k)
|
86
|
+
# end
|
87
87
|
end
|
88
88
|
it_behaves_like "retains initialization options"
|
89
89
|
it_behaves_like "ruby pojo"
|
data/spec/spec_helper.rb
CHANGED
@@ -38,18 +38,17 @@ RSpec.shared_examples "marshalable ruby pojo" do
|
|
38
38
|
it "raises an 'NoMethodError' error when attribute does not exist" do
|
39
39
|
expect { @obj.address }.to raise_error NoMethodError
|
40
40
|
end
|
41
|
+
it "#attributes method excludes internal attributes unless overridden." do
|
42
|
+
expect(@obj.attributes[:skn_enabled_depth]).to be_nil
|
43
|
+
expect(@obj.attributes(true)[:skn_enabled_depth]).to be_nil
|
44
|
+
expect(@obj.attributes(false)[:skn_enabled_depth]).to eql @obj.depth_level
|
45
|
+
end
|
41
46
|
context "transformations are enabled with " do
|
42
|
-
it "#to_json method returns a serialized version of this object." do
|
43
|
-
expect(object.to_json).to include(":\"")
|
44
|
-
end
|
45
|
-
it "#to_xml method returns a serialized version of this object." do
|
46
|
-
expect(object.to_xml).to include("xml version")
|
47
|
-
end
|
48
47
|
it "#to_hash method returns a serialized version of this object." do
|
49
|
-
expect(
|
48
|
+
expect(@obj.to_hash).to be_a(Hash)
|
50
49
|
end
|
51
50
|
it "#attributes method returns original input hash." do
|
52
|
-
expect(
|
51
|
+
expect(@obj.attributes).to be_a(Hash)
|
53
52
|
end
|
54
53
|
end
|
55
54
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
##
|
2
2
|
# <root>/spec/support/shared_example_ruby_pojo.rb
|
3
3
|
#
|
4
|
-
# refs: result_bean
|
4
|
+
# refs: result_bean
|
5
5
|
#
|
6
6
|
|
7
7
|
RSpec.shared_examples "ruby pojo" do
|
@@ -35,31 +35,25 @@ RSpec.shared_examples "ruby pojo" do
|
|
35
35
|
it "raises an 'NoMethodError' error when attribute that does not exist is accessed " do
|
36
36
|
expect { @obj.address }.to raise_error NoMethodError
|
37
37
|
end
|
38
|
-
it "Nests objects if multi-level hash is given " do
|
39
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two", three: {four: 4, five: 5}})
|
40
|
-
expect(object.three).to be_kind_of(SknUtils::NestedResultBase)
|
41
|
-
expect(object.three.five).to eq(5)
|
42
|
-
end
|
43
38
|
it "#attributes method returns a hash of all attributes and their values." do
|
44
|
-
expect(
|
45
|
-
expect(
|
46
|
-
expect(
|
39
|
+
expect(@obj.attributes).to be_a(Hash)
|
40
|
+
expect(@obj.attributes[:one]).to eql("one")
|
41
|
+
expect(@obj.attributes[:three]).to be_a(Hash)
|
42
|
+
end
|
43
|
+
it "#attributes method excludes internal attributes unless overridden." do
|
44
|
+
expect(@obj.attributes[:skn_enabled_depth]).to be_nil
|
45
|
+
expect(@obj.attributes(true)[:skn_enabled_depth]).to be_nil
|
46
|
+
expect(@obj.attributes(false)[:skn_enabled_depth]).to eql @obj.depth_level
|
47
47
|
end
|
48
48
|
|
49
49
|
context "transformations are enabled with " do
|
50
50
|
it "#attributes method returns a hash of all attributes and their values." do
|
51
|
-
expect(
|
52
|
-
expect(
|
53
|
-
expect(
|
51
|
+
expect(@obj.attributes).to be_a(Hash)
|
52
|
+
expect(@obj.attributes[:one]).to be_eql("one")
|
53
|
+
expect(@obj.attributes[:three]).to be_a(Hash)
|
54
54
|
end
|
55
|
-
it "#to_json method returns a serialized version of this object." do
|
56
|
-
expect(object.to_json).to include(":\"")
|
57
|
-
end
|
58
|
-
it "#to_xml method returns a serialized version of this object." do
|
59
|
-
expect(object.to_xml).to include("xml version")
|
60
|
-
end
|
61
55
|
it "#to_hash method returns a serialized version of this object." do
|
62
|
-
expect(
|
56
|
+
expect(@obj.to_hash).to be_a(Hash)
|
63
57
|
end
|
64
58
|
end
|
65
59
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skn_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.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: 2015-
|
11
|
+
date: 2015-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activemodel
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '3.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,13 +94,11 @@ files:
|
|
108
94
|
- lib/skn_utils/nested_result_base.rb
|
109
95
|
- lib/skn_utils/page_controls.rb
|
110
96
|
- lib/skn_utils/result_bean.rb
|
111
|
-
- lib/skn_utils/result_bean_with_errors.rb
|
112
97
|
- lib/skn_utils/version.rb
|
113
98
|
- skn_utils.gemspec
|
114
99
|
- spec/lib/skn_utils/generic_bean_spec.rb
|
115
100
|
- spec/lib/skn_utils/page_controls_spec.rb
|
116
101
|
- spec/lib/skn_utils/result_bean_spec.rb
|
117
|
-
- spec/lib/skn_utils/result_bean_with_errors_spec.rb
|
118
102
|
- spec/spec_helper.rb
|
119
103
|
- spec/support/shared_example_marshalable_ruby_pojo.rb
|
120
104
|
- spec/support/shared_example_ruby_pojo.rb
|
@@ -138,18 +122,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
122
|
version: '0'
|
139
123
|
requirements: []
|
140
124
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.4.
|
125
|
+
rubygems_version: 2.4.8
|
142
126
|
signing_key:
|
143
127
|
specification_version: 3
|
144
128
|
summary: Ruby convenience utilities, the first being a ResultBean. ResultBean is
|
145
129
|
a PORO (Plain Old Ruby Object) which inherits from NestedResultBean class (inlcuded).
|
146
|
-
This class is
|
147
|
-
via dot or hash notation, and is serializable
|
130
|
+
This class is instantiated via a hash at Ruby Runtime, allowing access to vars
|
131
|
+
via dot or hash notation, and is serializable (<obj>.to_hash) using standard Hash
|
132
|
+
serialization methods.
|
148
133
|
test_files:
|
149
134
|
- spec/lib/skn_utils/generic_bean_spec.rb
|
150
135
|
- spec/lib/skn_utils/page_controls_spec.rb
|
151
136
|
- spec/lib/skn_utils/result_bean_spec.rb
|
152
|
-
- spec/lib/skn_utils/result_bean_with_errors_spec.rb
|
153
137
|
- spec/spec_helper.rb
|
154
138
|
- spec/support/shared_example_marshalable_ruby_pojo.rb
|
155
139
|
- spec/support/shared_example_ruby_pojo.rb
|
@@ -1,47 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# <Rails.root>/lib/skn_utils/result_bean_with_errors.rb
|
3
|
-
#
|
4
|
-
# *** See SknUtils::NestedResultBase for details ***
|
5
|
-
#
|
6
|
-
##
|
7
|
-
# (Defaults)
|
8
|
-
# :enable_serialization = false -- for speed
|
9
|
-
# :depth = :multi
|
10
|
-
##
|
11
|
-
# Add the ActiveModel::Errors Object to bean structure, and
|
12
|
-
# filters @errors out of serialization features; i.e. not included in *.attributes()
|
13
|
-
#
|
14
|
-
# bean.errors.add(:name, "can not be nil") if name == nil
|
15
|
-
###
|
16
|
-
|
17
|
-
module SknUtils
|
18
|
-
|
19
|
-
class ResultBeanWithErrors < NestedResultBase
|
20
|
-
include ActiveModel::Conversion
|
21
|
-
extend ActiveModel::Naming
|
22
|
-
|
23
|
-
attr_reader :errors
|
24
|
-
|
25
|
-
#:nodoc:
|
26
|
-
def initialize(params={})
|
27
|
-
@errors = params.delete :errors
|
28
|
-
@errors = ActiveModel::Errors.new(self) unless @errors.present?
|
29
|
-
super(params)
|
30
|
-
end
|
31
|
-
|
32
|
-
#:nodoc:
|
33
|
-
def read_attribute_for_validation(attr)
|
34
|
-
send(attr)
|
35
|
-
end
|
36
|
-
|
37
|
-
#:nodoc:
|
38
|
-
def self.human_attribute_name(attr, options = {})
|
39
|
-
attr
|
40
|
-
end
|
41
|
-
|
42
|
-
#:nodoc:
|
43
|
-
def self.lookup_ancestors
|
44
|
-
[self]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,178 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# spec/lib/skn_utils/result_bean_with_errors_spec.rb
|
3
|
-
#
|
4
|
-
|
5
|
-
RSpec.describe SknUtils::ResultBeanWithErrors, "Result Bean class with ActiveModel::Errors object " do
|
6
|
-
let(:object) {
|
7
|
-
SknUtils::ResultBeanWithErrors.new({one: "one",
|
8
|
-
two: "two",
|
9
|
-
three: {four: 4, five: 5, six: {seven: 7, eight: "eight" }},
|
10
|
-
four: {any_key: "any value"},
|
11
|
-
five: []
|
12
|
-
})
|
13
|
-
}
|
14
|
-
|
15
|
-
context "Internal Operations, assuming :dept => :multi and enable_serialization => false" do
|
16
|
-
it "Creates an empty bean if no params are passed" do
|
17
|
-
is_expected.to be
|
18
|
-
expect(subject.errors).to be
|
19
|
-
end
|
20
|
-
it "Initializes from a hash that DOES NOT include an errors.object " do
|
21
|
-
expect(SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})).to be
|
22
|
-
end
|
23
|
-
it "Initializes from a hash that DOES include an errors.object " do
|
24
|
-
errors = ActiveModel::Errors.new(self) ## VERY BAD IDEAL
|
25
|
-
expect(SknUtils::ResultBeanWithErrors.new({one: "one", two: "two", errors: errors})).to be
|
26
|
-
end
|
27
|
-
it "Does not modify the base class, only singleton instance methods" do
|
28
|
-
obj1 = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
|
29
|
-
obj2 = SknUtils::ResultBeanWithErrors.new({three: "3", four: "4"})
|
30
|
-
expect(obj1.one).to eql "one"
|
31
|
-
expect(obj2.three).to eql "3"
|
32
|
-
expect(obj2.one?).to be_falsey
|
33
|
-
expect(obj1.three?).to be_falsey
|
34
|
-
expect { obj1.three }.to raise_error NoMethodError
|
35
|
-
expect { obj2.one }.to raise_error NoMethodError
|
36
|
-
end
|
37
|
-
it "Supports - respond_to - methods, because it has accessor methods" do
|
38
|
-
expect(object).to respond_to(:one)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
shared_examples_for "retains initialization options" do
|
43
|
-
it "retains depth_level option flag" do
|
44
|
-
expect(@obj.depth_level).to eql(:multi)
|
45
|
-
end
|
46
|
-
it "retains serialization option flag" do
|
47
|
-
expect(@obj.serialization_required?).to be false
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
context "ActiveModel:Errors object" do
|
52
|
-
it "#errors method returns an ActiveModel::Errors object" do
|
53
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
|
54
|
-
expect(obj.errors).to be_an_instance_of(ActiveModel::Errors)
|
55
|
-
end
|
56
|
-
|
57
|
-
it "#errors method accepts additional errors" do
|
58
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
|
59
|
-
obj.errors.add(:one,"must be numeric.")
|
60
|
-
expect(obj.errors.size).to be 1
|
61
|
-
end
|
62
|
-
|
63
|
-
it "#errors.full_messages method returns messages" do
|
64
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: "two"})
|
65
|
-
obj.errors.add(:one,"must be numeric.")
|
66
|
-
expect(obj.errors.full_messages.first).to include("numeric")
|
67
|
-
end
|
68
|
-
|
69
|
-
it "#errors.add_on_empty method correctly adds new errors" do
|
70
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
71
|
-
obj.errors.add_on_empty(:two)
|
72
|
-
expect(obj.errors.count).to be 1
|
73
|
-
end
|
74
|
-
|
75
|
-
it "#errors.add_on_blank method correctly adds new errors" do
|
76
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
77
|
-
obj.errors.add_on_blank(:two)
|
78
|
-
expect(obj.errors.count).to be 1
|
79
|
-
end
|
80
|
-
|
81
|
-
it "#errors.get method correctly retrieves existing message by attribute" do
|
82
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
83
|
-
obj.errors.add_on_blank(:two)
|
84
|
-
expect(obj.errors.get(:two).first).to include("blank")
|
85
|
-
end
|
86
|
-
|
87
|
-
it "#errors[] method correctly retrieves existing message by attribute" do
|
88
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
89
|
-
obj.errors.add_on_blank(:two)
|
90
|
-
expect(obj.errors[:two].first).to include("blank")
|
91
|
-
end
|
92
|
-
|
93
|
-
it "#errors.set method correctly adds sets message on attribute" do
|
94
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
95
|
-
obj.errors.set(:two, "Required value, must not be empty")
|
96
|
-
expect(obj.errors.get(:two)).to include("Required")
|
97
|
-
end
|
98
|
-
|
99
|
-
it "#errors.include? method correctly determines that an error exists for the given key" do
|
100
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
101
|
-
obj.errors.add(:two, "Required value, must not be empty")
|
102
|
-
result = obj.errors.include?(:two)
|
103
|
-
expect(result).to be_truthy
|
104
|
-
result = obj.errors.include?(:one)
|
105
|
-
expect(result).to be_falsey
|
106
|
-
end
|
107
|
-
|
108
|
-
it "#errors.delete method correctly removes an error for the given key" do
|
109
|
-
obj = SknUtils::ResultBeanWithErrors.new({one: "one", two: ""})
|
110
|
-
obj.errors.add(:two, "Required value, must not be empty")
|
111
|
-
result = obj.errors.include?(:two)
|
112
|
-
expect(result).to be_truthy
|
113
|
-
obj.errors.delete(:two)
|
114
|
-
result = obj.errors.include?(:two)
|
115
|
-
expect(result).to be_falsey
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
context "Serialization" do
|
120
|
-
before :each do
|
121
|
-
@obj = object
|
122
|
-
end
|
123
|
-
it "Serialization does not include the errors object." do
|
124
|
-
expect(@obj.to_hash[:errors]).not_to be
|
125
|
-
expect(@obj.errors).to be_a(ActiveModel::Errors)
|
126
|
-
end
|
127
|
-
|
128
|
-
it_behaves_like "retains initialization options"
|
129
|
-
it_behaves_like "ruby pojo"
|
130
|
-
end
|
131
|
-
|
132
|
-
context "Basic Operations after Marshal marshaling " do
|
133
|
-
it "Singleton objects (like ResultBean) cannot be marshaled" do
|
134
|
-
expect { Marshal.dump(object) }.to raise_error TypeError
|
135
|
-
end
|
136
|
-
end
|
137
|
-
context "Basic Operations without marshaling " do
|
138
|
-
before :each do
|
139
|
-
@obj = object
|
140
|
-
end
|
141
|
-
it_behaves_like "retains initialization options"
|
142
|
-
it_behaves_like "ruby pojo"
|
143
|
-
end
|
144
|
-
context "Basic Operations after Yaml marshaling " do
|
145
|
-
before :each do
|
146
|
-
dmp = YAML::dump(object)
|
147
|
-
@obj = YAML::load(dmp)
|
148
|
-
end
|
149
|
-
it_behaves_like "retains initialization options"
|
150
|
-
it_behaves_like "ruby pojo"
|
151
|
-
end
|
152
|
-
context "ResultBeans stripped of their internal singleton accessors can be Marshaled! " do
|
153
|
-
before :each do
|
154
|
-
dmp = YAML::dump(object)
|
155
|
-
obj = YAML::load(dmp) # Yaml'ing removes singleton accessor methods'
|
156
|
-
# by initializing object without using its
|
157
|
-
# initialize() method
|
158
|
-
|
159
|
-
dmp = Marshal.dump(obj) # Now Marshal load/dump will work
|
160
|
-
@obj = Marshal.load(dmp) # Use GenericBean if Marshal support is needed
|
161
|
-
end
|
162
|
-
it_behaves_like "retains initialization options"
|
163
|
-
it_behaves_like "ruby pojo"
|
164
|
-
end
|
165
|
-
context "Basic Operations after Yaml marshaling via restored accessors " do
|
166
|
-
before :each do
|
167
|
-
dmp = YAML::dump(object)
|
168
|
-
@obj = YAML::load(dmp)
|
169
|
-
# Restore setters
|
170
|
-
@obj.attributes.keys.each do |k|
|
171
|
-
@obj.singleton_class.send(:attr_accessor, k)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
it_behaves_like "retains initialization options"
|
175
|
-
it_behaves_like "ruby pojo"
|
176
|
-
end
|
177
|
-
|
178
|
-
end
|