attribute_struct 0.2.28 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41547b7309813fb1da48c6e17e0d063215d08963
4
- data.tar.gz: 9ebfd315aab3eecc4a92d6a08c3276bddd9538ba
3
+ metadata.gz: 8589e76432a36f05a1450f97e802269ef8edb8df
4
+ data.tar.gz: 6364945c9d3ccb645eb54e2a419675a7d4f2ad61
5
5
  SHA512:
6
- metadata.gz: bb2c29323b1d75a607f097d49e79e5f91649810ae7c066651c09cd890fbe6c0c0266df29930d16c8f8cd5887345dcb9169064cbeb3145d129ca6742590c7194f
7
- data.tar.gz: bfd1e337210551aea3a1c090ba09b84431b44a1f90d0eaa88d6e25fbfa4412289b6af1400dfb95cb255661d5e17ab3154c0c0f06bc584086bd127da4444e30ab
6
+ metadata.gz: 1bf46e3d433e2718593b6981303a88226b38aff6b421028d1b23f79fb7bdf765a7f800a2c0d35a4d33323f17f3a2a33f73b201d8aee88fec0b68aa1b4757d8b6
7
+ data.tar.gz: e26b766049f6bd19ba1b9e54bae280ae97372d5b438ee15bd1c44f97d8d20b2c802461a9f14721a3eaa98ee65f83f9a4a412fbe2faee590b4b980ff97aed05e1
data/CHANGELOG.md CHANGED
@@ -1,80 +1,85 @@
1
- ## v0.2.28
1
+ # v0.3.0
2
+ * Only allow forced key processing when camel casing is enabled
3
+ * Refactored dump implementation to better handle deeply nested structs
4
+ * Add missing bang method aliases
5
+
6
+ # v0.2.28
2
7
  * Set internal data at creation time, not after evaluation
3
8
 
4
- ## v0.2.26
9
+ # v0.2.26
5
10
  * Add support for lowercase leading camel casing
6
11
 
7
- ## v0.2.24
12
+ # v0.2.24
8
13
  * Fix `#_root` helper to properly check for parent
9
14
  * Always use the `#_klass_new` helper
10
15
  * Support optional arguments/block to `#_klass_new`
11
16
 
12
- ## v0.2.22
17
+ # v0.2.22
13
18
  * Add more helper method bang aliases
14
19
  * Properly persist camel data on Hash keys
15
20
  * Support optional automatic AttributeStruct loading on Hash set
16
21
 
17
- ## v0.2.20
22
+ # v0.2.20
18
23
  * Fix: remove nil structs
19
24
 
20
- ## v0.2.18
25
+ # v0.2.18
21
26
  * Fix `AttributeStruct#dump!` to properly handle nil-type values
22
27
 
23
- ## v0.2.16
28
+ # v0.2.16
24
29
  * Fix regression mixed argument and block set returning second level struct
25
30
 
26
- ## v0.2.14
31
+ # v0.2.14
27
32
  * Fix `:value_collapse` option to prevent multiple nestings
28
33
 
29
- ## v0.2.12
34
+ # v0.2.12
30
35
  * Implementation updates to monkey camels helper
31
36
  * Provide bang style helper methods for all helpers
32
37
 
33
- ## v0.2.10
38
+ # v0.2.10
34
39
  * Add support for multi parameter set
35
40
 
36
- ## v0.2.8
41
+ # v0.2.8
37
42
  * Fix class mismatch issue
38
43
 
39
- ## v0.2.6
44
+ # v0.2.6
40
45
  * Vendor `Mash` and expand to provide required deep_merge functionality
41
46
  * Remove external dependencies
42
47
 
43
- ## v0.2.4
48
+ # v0.2.4
44
49
  * Revert #class method removal (required by hash helpers when duping)
45
50
  * Set base prior to path walking
46
51
  * Initialize struct if nil is encountered
47
52
  * Collapse values at leaf
48
53
 
49
- ## v0.2.2
54
+ # v0.2.2
50
55
  * Update block evaluation assignment to prevent value knockout
51
56
  * Fix `#is_a?` behavior and include base class in check list
52
57
  * Add `#respond_to?` method
53
58
  * Add irb helper module
54
59
 
55
- ## v0.2.0
60
+ # v0.2.0
56
61
  * Add support for value setting into given context level
57
62
  * Add #build helper method
58
63
  * Introduce `:value_collapse` option for multi set combination instead of replacement
59
64
  * Provide bang suffix aliases
60
65
 
61
- ## v0.1.8
66
+ # v0.1.8
62
67
  * Basic (optional) auto camel detection on import
63
68
  * Add hash helper methods out to class
64
69
 
65
- ## v0.1.6
70
+ # v0.1.6
66
71
  * Add helpers for walking up the tree
67
72
  * Update hashie dependency restriction
68
73
 
69
- ## v0.1.4
74
+ # v0.1.4
70
75
  * Add `_array` helper
71
76
  * Ensure all helpers are using underscore prefix
72
77
  * Inherit from BasicObject
73
78
  * Allow struct discovery in enumerable objects
74
79
  * Add more helpers
75
80
 
76
- ## v0.1.2
81
+ # v0.1.2
77
82
  * Fix naming in require
78
83
 
79
- ## v0.1.0
84
+ # v0.1.0
80
85
  * Initial release
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2014 Chris Roberts
1
+ Copyright 2016 Chris Roberts
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -1,66 +1,256 @@
1
1
  # AttributeStruct
2
2
 
3
- This is a helper library that essentially builds hashes. It
4
- wraps hash building with a nice DSL to make it slightly cleaner,
5
- more robust, and provide extra features.
3
+ AttributeStruct is a DSL helper library. It provides support for programmatic
4
+ generation of complex data structures.
6
5
 
7
- ## Build Status
6
+ ## How it works
8
7
 
9
- * [![Build Status](https://api.travis-ci.org/chrisroberts/attribute_struct.png)](https://travis-ci.org/chrisroberts/attribute_struct)
8
+ Under the hood, AttributeStruct makes use of Ruby's `BasicObject` class and the
9
+ `#method_missing` method to bring a clean and concise way of generating data
10
+ structures. Deeply nested Hashes can be built using method chaining, block
11
+ structures, or both. Evaluation of a structure is performed top down, allowing
12
+ access to previously set data values within the structure during evaluation.
10
13
 
11
- ## Usage
14
+ ## Examples
15
+
16
+ ### Setting values
17
+
18
+ #### Method chaining
19
+
20
+ ```ruby
21
+ require 'attribute_struct'
22
+
23
+ AttributeStruct.new do
24
+ this.is.a.deeply.nested.hash true
25
+ end.dump!
26
+
27
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>true}}}}}}
28
+ ```
29
+
30
+ #### Block nesting
31
+
32
+ ```ruby
33
+ require 'attribute_struct'
34
+
35
+ AttributeStruct.new do
36
+ this do
37
+ is do
38
+ a do
39
+ deeply do
40
+ nested do
41
+ hash true
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end.dump!
48
+
49
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>true}}}}}}
50
+ ```
51
+
52
+ #### Mixed block nesting and method chaining
53
+
54
+ ```ruby
55
+ require 'attribute_struct'
56
+
57
+ AttributeStruct.new do
58
+ this.is.a do
59
+ deeply.nested do
60
+ hash true
61
+ end
62
+ end
63
+ end.dump!
64
+
65
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>true}}}}}}
66
+ ```
67
+
68
+ ### Structure re-entry
69
+
70
+ #### Block re-entry
71
+
72
+ ```ruby
73
+ require 'attribute_struct'
74
+
75
+ AttributeStruct.new do
76
+ this.is.a do
77
+ deeply.nested do
78
+ hash true
79
+ end
80
+ deeply do
81
+ nested.other_hash true
82
+ end
83
+ end
84
+ end.dump!
85
+
86
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>true,"other_hash"=>true}}}}}}
87
+ ```
88
+
89
+ #### Method re-entry
90
+
91
+ ```ruby
92
+ require 'attribute_struct'
93
+
94
+ AttributeStruct.new do
95
+ this.is.a do
96
+ deeply.nested do
97
+ hash true
98
+ end
99
+ end
100
+ this.is.a.deeply.nested.other_hash true
101
+ end.dump!
102
+
103
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>true,"other_hash"=>true}}}}}}
104
+ ```
105
+
106
+ ### Data removal
107
+
108
+ ```ruby
109
+ require 'attribute_struct'
110
+
111
+ AttributeStruct.new do
112
+ this.is.a do
113
+ deeply.nested do
114
+ hash true
115
+ end
116
+ end
117
+ this.is.a.deeply.nested.other_hash true
118
+ this.is.a.deeply.nested.delete!(:hash)
119
+ end.dump!
120
+
121
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"other_hash"=>true}}}}}}
122
+ ```
123
+
124
+ ### Data Access
125
+
126
+ #### Current data
127
+
128
+ ```ruby
129
+ require 'attribute_struct'
130
+
131
+ AttributeStruct.new do
132
+ this.is.a do
133
+ deeply.nested do
134
+ hash 'my_value'
135
+ end
136
+ end
137
+ this.is.a.deeply.nested do
138
+ other_hash data![:hash]
139
+ end
140
+ end.dump!
141
+
142
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>"my_value","other_hash"=>"my_value"}}}}}}
143
+ ```
144
+
145
+ #### Current data keys
12
146
 
13
147
  ```ruby
14
148
  require 'attribute_struct'
15
149
 
16
- struct = AttributeStruct.new
17
- struct.settings do
18
- ui.admin do
19
- enabled true
20
- port 8080
21
- bind '*'
150
+ AttributeStruct.new do
151
+ this.is.a do
152
+ deeply.nested do
153
+ hash 'my_value'
154
+ end
22
155
  end
23
- ui.public do
24
- enabled true
25
- port 80
26
- bind '*'
156
+ this.is.a.deeply.nested do
157
+ other_hash keys!
27
158
  end
28
- client('general') do
29
- enabled false
159
+ end.dump!
160
+
161
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nested"=>{"hash"=>"my_value","other_hash"=>["hash"]}}}}}}
162
+ ```
163
+
164
+ ### Hierarchy access
165
+
166
+ #### Parent structure
167
+
168
+ ```ruby
169
+ require 'attribute_struct'
170
+
171
+ AttributeStruct.new do
172
+ this.is.a do
173
+ deeply do
174
+ state 'sunny'
175
+ nested do
176
+ hash parent!.state
177
+ end
178
+ end
30
179
  end
31
- end
180
+ end.dump!
181
+
182
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"state"=>"sunny", "nested"=>{"hash"=>"sunny"}}}}}}
32
183
  ```
33
184
 
34
- Now we have an attribute structure that we can
35
- query and modify. To force it to a hash, we
36
- can simply dump it:
185
+ #### Root structure
37
186
 
38
187
  ```ruby
39
- require 'pp'
188
+ require 'attribute_struct'
189
+
190
+ AttributeStruct.new do
191
+ this.is.a do
192
+ deeply do
193
+ state 'sunny'
194
+ nested do
195
+ hash root!.this.is.a.deeply.state
196
+ end
197
+ end
198
+ end
199
+ end.dump!
40
200
 
41
- pp struct._dump
201
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"state"=>"sunny", "nested"=>{"hash"=>"sunny"}}}}}}
42
202
  ```
43
203
 
44
- which gives:
204
+ ### Camel case
205
+
206
+ #### Camel case keys
45
207
 
46
208
  ```ruby
47
- {"settings"=>
48
- {"ui"=>
49
- {"admin"=>{"enabled"=>true, "port"=>8080, "bind"=>"*"},
50
- "public"=>{"enabled"=>true, "port"=>80, "bind"=>"*"}},
51
- "client"=>{"general"=>{"enabled"=>false}}}}
209
+ require 'attribute_struct'
210
+
211
+ AttributeStruct.new do
212
+ self._camel_keys = true
213
+ this.is.a.deeply.nested_camel.hash true
214
+ end.dump!
215
+
216
+ # => {"This"=>{"Is"=>{"A"=>{"Deeply"=>{"NestedCamel"=>{"Hash"=>true}}}}}}
52
217
  ```
53
218
 
54
- ## IRB
219
+ #### Camel case with lead lower
220
+
221
+ ```ruby
222
+ require 'attribute_struct'
223
+
224
+ AttributeStruct.new do
225
+ self._camel_keys = true
226
+ self._camel_style = :no_leading
227
+ this.is.a.deeply.nested_camel.hash true
228
+ end.dump!
55
229
 
56
- IRB expects some things to be around like `#inspect` and `#to_s`. Before
57
- using `AttributeStruct` in IRB, enable compat mode:
230
+ # => {"this"=>{"is"=>{"a"=>{"deeply"=>{"nestedCamel"=>{"hash"=>true}}}}}}
231
+ ```
232
+
233
+ #### Disable camel on individual key
58
234
 
59
235
  ```ruby
60
- > require 'attribute_struct'
61
- > AttributeStruct.irb_compat!
236
+ require 'attribute_struct'
237
+
238
+ AttributeStruct.new do
239
+ self._camel_keys = true
240
+ this.is.a.deeply.nested_camel.hash true
241
+ this.set!('horse'.no_hump!, true)
242
+ end.dump!
243
+
244
+ # => {"This"=>{"Is"=>{"A"=>{"Deeply"=>{"NestedCamel"=>{"Hash"=>true}}}}},"horse" => true}
62
245
  ```
63
246
 
247
+ ## In the wild
248
+
249
+ Libraries utilizing AttributeStruct:
250
+
251
+ * SparkleFormation: http://www.sparkleformation.io
252
+ * Bogo Config: https://github.com/spox/bogo-config
253
+
64
254
  ## Information
65
255
 
66
256
  * Repo: https://github.com/chrisroberts/attribute_struct
@@ -8,7 +8,7 @@ class AttributeStruct < BasicObject
8
8
 
9
9
  # @return [Hash] valid styles and mapped value
10
10
  VALID_CAMEL_STYLES = {
11
- :bactrain => :no_leading,
11
+ :bactrian => :no_leading,
12
12
  :no_leading_hump => :no_leading,
13
13
  :no_leading => :no_leading,
14
14
  :dromedary => :leading,
@@ -87,10 +87,13 @@ class AttributeStruct < BasicObject
87
87
 
88
88
  # @return [Truthy, Falsey] current camelizing setting
89
89
  attr_reader :_camel_keys
90
+ alias_method :camel_keys!, :_camel_keys
90
91
  # @return [Symbol] current camel style
91
92
  attr_reader :_camel_style
93
+ alias_method :camel_style!, :_camel_style
92
94
  # @return [AtributeStruct::AttributeHash, Mash] holding space for state
93
95
  attr_reader :_arg_state
96
+ alias_method :arg_state!, :_arg_state
94
97
 
95
98
  # Create new instance
96
99
  #
@@ -300,6 +303,11 @@ class AttributeStruct < BasicObject
300
303
  _data.empty?
301
304
  end
302
305
 
306
+ # @return [TrueClass, FalseClass] struct is present (not empty)
307
+ def present?
308
+ !nil?
309
+ end
310
+
303
311
  # Determine if self is a class
304
312
  #
305
313
  # @param klass [Class]
@@ -330,22 +338,39 @@ class AttributeStruct < BasicObject
330
338
  end
331
339
  alias_method :delete!, :_delete
332
340
 
333
- # @return [AttributeStruct::AttributeHash, Mash] dump struct to hashish
334
- def _dump
335
- processed = @table.map do |key, value|
336
- if(value.is_a?(::Enumerable))
337
- flat = value.map do |v|
338
- v.is_a?(_klass) ? v._dump : v
339
- end
340
- val = value.is_a?(::Hash) ? __hashish[*flat.flatten(1)] : flat
341
- elsif(value.is_a?(_klass) && value.nil?)
342
- next
343
- elsif(value.is_a?(_klass) && !value.nil?)
344
- val = value._dump
341
+ # Process and unpack items for dumping within deeply nested
342
+ # enumerable types
343
+ #
344
+ # @param item [Object]
345
+ # @return [Object]
346
+ def _dump_unpacker(item)
347
+ if(item.is_a?(::Enumerable))
348
+ if(item.respond_to?(:keys))
349
+ item.class[
350
+ *item.map do |entry|
351
+ _dump_unpacker(entry)
352
+ end.flatten(1)
353
+ ]
345
354
  else
346
- val = value.nil? ? nil : value
355
+ item.class[
356
+ *item.map do |entry|
357
+ _dump_unpacker(entry)
358
+ end
359
+ ]
347
360
  end
348
- [key, val]
361
+ elsif(item.is_a?(::AttributeStruct))
362
+ item.nil? ? :__unset__ : item._dump
363
+ else
364
+ item
365
+ end
366
+ end
367
+
368
+ # @return [AttributeStruct::AttributeHash, Mash] dump struct to hashish
369
+ def _dump
370
+ processed = @table.keys.map do |key|
371
+ value = @table[key]
372
+ val = _dump_unpacker(value)
373
+ [_dump_unpacker(key), val] unless val == :__unset__
349
374
  end.compact
350
375
  __hashish[*processed.flatten(1)]
351
376
  end
@@ -453,7 +478,7 @@ class AttributeStruct < BasicObject
453
478
  key._hump
454
479
  end
455
480
  end
456
- if((_camel_keys && key._camel?) || args.include?(:force))
481
+ if(_camel_keys && (key._camel? || args.include?(:force)))
457
482
  camel_args = [key]
458
483
  if(key._hump_style || _camel_style == :no_leading)
459
484
  unless(key._hump_style == :leading_hump)
@@ -73,13 +73,13 @@ unless(defined?(MonkeyCamels))
73
73
  # Set hump style to non-leading upcase
74
74
  #
75
75
  # @return [self]
76
- def _bactrain
76
+ def _bactrian
77
77
  @__not_camel = false
78
78
  @__hump_style = :no_leading_hump
79
79
  self
80
80
  end
81
- alias_method :bactrain!, :_bactrain
82
- alias_method :no_leading_hump!, :_bactrain
81
+ alias_method :bactrian!, :_bactrian
82
+ alias_method :no_leading_hump!, :_bactrian
83
83
 
84
84
  # Set hump style to leading upcase
85
85
  #
@@ -1,4 +1,4 @@
1
1
  class AttributeStruct < BasicObject
2
2
  # Current library version
3
- VERSION = ::Gem::Version.new('0.2.28')
3
+ VERSION = ::Gem::Version.new('0.3.0')
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attribute_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.28
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-30 00:00:00.000000000 Z
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bogo