skn_utils 1.5.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|