deep-hash-struct 0.1.1 → 0.1.2
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/.travis.yml +2 -2
- data/README.md +5 -9
- data/lib/deep/hash/struct.rb +346 -21
- data/lib/deep/hash/struct/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d75b9bdee86a1e833867d5f5c09a39af09dbe262
|
4
|
+
data.tar.gz: a9b9534aeb425c24a0cabc04f03ce417876c344f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d3676edb4c79c1dfcd232c9c550b00afd1acba038c39b389f719239c2948fb843c34be45e70ffb0e7d1389c01aa81c96026e158cd18668362955e48702d46bf
|
7
|
+
data.tar.gz: c882419641decdce45a9bbb6a6ae139ef8ca76730785b8c1b449e02da0b78f56a21a403dc36f867635e54da9257ad5b65425161a2f0967716b4ba1078d767ae9
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Deep::Hash::Struct
|
2
2
|
|
3
|
-
|
3
|
+
Struct copes with the operation that is Deep.
|
4
|
+
Because the data maintenance of many hierarchies became possible, I can treat it like Hash.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -20,18 +21,14 @@ Or install it yourself as:
|
|
20
21
|
|
21
22
|
## Usage
|
22
23
|
|
24
|
+
```ruby
|
23
25
|
wrapper = Deep::Hash::Struct::Wrapper.new
|
24
26
|
wrapper.a = 1
|
25
27
|
wrapper.b.a = 2
|
26
28
|
wrapper[:c][:a] = 3
|
27
29
|
wrapper[:c].b = 4
|
28
|
-
wrapper.to_h
|
29
|
-
|
30
|
-
## Development
|
31
|
-
|
32
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
33
|
-
|
34
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
30
|
+
wrapper.to_h # => {:a=>1, :b=>{:a=>2}, :c=>{:a=>3, :b=>4}}
|
31
|
+
```
|
35
32
|
|
36
33
|
## Contributing
|
37
34
|
|
@@ -41,4 +38,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/etiopi
|
|
41
38
|
## License
|
42
39
|
|
43
40
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
44
|
-
|
data/lib/deep/hash/struct.rb
CHANGED
@@ -5,17 +5,25 @@ module Deep
|
|
5
5
|
module Hash
|
6
6
|
module Struct
|
7
7
|
class Wrapper
|
8
|
+
attr_accessor :default
|
9
|
+
|
8
10
|
def initialize(h = {})
|
9
11
|
return if h.nil? || h.count.zero?
|
10
12
|
wrap h, self
|
11
13
|
end
|
12
14
|
|
13
15
|
def keys
|
14
|
-
instance_variables.map do |k|
|
16
|
+
instance_variables.select { |k| k !~ /default/ }.map do |k|
|
15
17
|
k.to_s[1..-1].to_sym
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
def values
|
22
|
+
keys.map do |k|
|
23
|
+
self[k]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
19
27
|
def [](k)
|
20
28
|
__send__ k
|
21
29
|
end
|
@@ -24,16 +32,53 @@ module Deep
|
|
24
32
|
__send__ "#{k}=", v
|
25
33
|
end
|
26
34
|
|
35
|
+
def ==(hash)
|
36
|
+
if hash.class == self.class
|
37
|
+
to_h == hash.to_h
|
38
|
+
else
|
39
|
+
to_h == hash
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def ===(klass)
|
44
|
+
self.class == klass
|
45
|
+
end
|
46
|
+
|
27
47
|
def each
|
48
|
+
if block_given?
|
49
|
+
keys.each do |k|
|
50
|
+
yield k, self[k]
|
51
|
+
end
|
52
|
+
else
|
53
|
+
to_h.each
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def each_with_index
|
58
|
+
index = 0
|
28
59
|
keys.each do |k|
|
29
|
-
yield k, self[k]
|
60
|
+
yield [k, self[k]], index
|
61
|
+
index += 1
|
30
62
|
end
|
31
63
|
end
|
32
64
|
|
33
|
-
def
|
65
|
+
def each_with_object(init)
|
66
|
+
each do |k, v|
|
67
|
+
yield [k, v], init
|
68
|
+
end
|
69
|
+
|
70
|
+
init
|
71
|
+
end
|
72
|
+
|
73
|
+
def each_key
|
34
74
|
keys.each do |k|
|
35
|
-
yield
|
36
|
-
|
75
|
+
yield k
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def each_value
|
80
|
+
values.each do |v|
|
81
|
+
yield v
|
37
82
|
end
|
38
83
|
end
|
39
84
|
|
@@ -42,12 +87,6 @@ module Deep
|
|
42
87
|
end
|
43
88
|
alias size count
|
44
89
|
|
45
|
-
def values
|
46
|
-
keys.map do |k|
|
47
|
-
self[k]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
90
|
def blank?
|
52
91
|
keys.size.zero?
|
53
92
|
end
|
@@ -57,15 +96,15 @@ module Deep
|
|
57
96
|
end
|
58
97
|
|
59
98
|
def dig(*syms)
|
60
|
-
syms.
|
61
|
-
h[k]
|
99
|
+
syms.inject(self) do |h, k|
|
100
|
+
h[k]
|
62
101
|
end
|
63
102
|
rescue
|
64
103
|
nil
|
65
104
|
end
|
66
105
|
|
67
106
|
def merge(hash)
|
68
|
-
klass =
|
107
|
+
klass = dup
|
69
108
|
|
70
109
|
hash.each do |k, v|
|
71
110
|
klass[k] = v
|
@@ -80,12 +119,13 @@ module Deep
|
|
80
119
|
end
|
81
120
|
self
|
82
121
|
end
|
122
|
+
alias update merge!
|
83
123
|
|
84
|
-
def deep_merge(hash)
|
85
|
-
klass =
|
124
|
+
def deep_merge(hash, klass = self)
|
125
|
+
klass = klass.dup
|
86
126
|
|
87
127
|
hash.each do |k , v|
|
88
|
-
klass[k] = hash?(v) ? deep_merge(v) : v
|
128
|
+
klass[k] = hash?(v) ? klass.deep_merge(v, klass[k]) : v
|
89
129
|
end
|
90
130
|
|
91
131
|
klass
|
@@ -99,6 +139,44 @@ module Deep
|
|
99
139
|
klass
|
100
140
|
end
|
101
141
|
|
142
|
+
def reverse_merge(hash)
|
143
|
+
klass = dup
|
144
|
+
|
145
|
+
hash.each do |k, v|
|
146
|
+
klass[k] = v if klass.exclude?(k)
|
147
|
+
end
|
148
|
+
|
149
|
+
klass
|
150
|
+
end
|
151
|
+
|
152
|
+
def reverse_merge!(hash)
|
153
|
+
hash.each do |k, v|
|
154
|
+
self[k] = v if exclude?(k)
|
155
|
+
end
|
156
|
+
|
157
|
+
self
|
158
|
+
end
|
159
|
+
|
160
|
+
def reverse_deep_merge(hash, klass = self)
|
161
|
+
klass = klass.dup
|
162
|
+
|
163
|
+
hash.each do |k , v|
|
164
|
+
next if !hash?(v) && klass.include?(k)
|
165
|
+
klass[k] = hash?(v) ? klass.reverse_deep_merge(v, klass[k]) : v
|
166
|
+
end
|
167
|
+
|
168
|
+
klass
|
169
|
+
end
|
170
|
+
|
171
|
+
def reverse_deep_merge!(hash)
|
172
|
+
hash.each do |k, v|
|
173
|
+
next if !hash?(v) && include?(k)
|
174
|
+
self[k] = hash?(v) ? reverse_deep_merge(v, self[k]) : v
|
175
|
+
end
|
176
|
+
|
177
|
+
self
|
178
|
+
end
|
179
|
+
|
102
180
|
def fetch(k, msg = nil)
|
103
181
|
v = self[k]
|
104
182
|
if block_given?
|
@@ -123,6 +201,252 @@ module Deep
|
|
123
201
|
end
|
124
202
|
end
|
125
203
|
|
204
|
+
def map
|
205
|
+
vs = []
|
206
|
+
|
207
|
+
each do |k, v|
|
208
|
+
vs << yield(k, v)
|
209
|
+
end
|
210
|
+
|
211
|
+
vs
|
212
|
+
end
|
213
|
+
alias collect map
|
214
|
+
|
215
|
+
def map_key
|
216
|
+
vs = []
|
217
|
+
|
218
|
+
keys.each do |k|
|
219
|
+
vs << yield(k)
|
220
|
+
end
|
221
|
+
|
222
|
+
vs
|
223
|
+
end
|
224
|
+
|
225
|
+
def map_value
|
226
|
+
vs = []
|
227
|
+
|
228
|
+
values.each do |v|
|
229
|
+
vs << yield(v)
|
230
|
+
end
|
231
|
+
|
232
|
+
vs
|
233
|
+
end
|
234
|
+
|
235
|
+
def fetch_values(*syms)
|
236
|
+
syms.map do |sym|
|
237
|
+
if block_given?
|
238
|
+
if keys.include?(sym)
|
239
|
+
self[sym]
|
240
|
+
else
|
241
|
+
yield sym
|
242
|
+
end
|
243
|
+
else
|
244
|
+
raise KeyError, "key not found: :#{sym}" unless keys.include?(sym)
|
245
|
+
self[sym]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def values_at(*syms)
|
251
|
+
syms.map do |sym|
|
252
|
+
v = self[sym]
|
253
|
+
(v.nil? || (v.class == self.class && v.blank?)) ? nil : v
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def invert
|
258
|
+
each_with_object({}) do |(k, v), h|
|
259
|
+
h[v] = k
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def delete(k)
|
264
|
+
remove_instance_variable "@#{k}"
|
265
|
+
end
|
266
|
+
|
267
|
+
def delete_if
|
268
|
+
each do |k, v|
|
269
|
+
remove_instance_variable "@#{k}" if yield(k, v)
|
270
|
+
end
|
271
|
+
self
|
272
|
+
end
|
273
|
+
|
274
|
+
def find
|
275
|
+
klass = self.class.new
|
276
|
+
|
277
|
+
each do |k, v|
|
278
|
+
if yield(k, v)
|
279
|
+
klass[k] = v
|
280
|
+
break
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
klass
|
285
|
+
end
|
286
|
+
|
287
|
+
def select
|
288
|
+
klass = self.class.new
|
289
|
+
|
290
|
+
each do |k, v|
|
291
|
+
klass[k] = v if yield(k, v)
|
292
|
+
end
|
293
|
+
|
294
|
+
klass
|
295
|
+
end
|
296
|
+
alias find_all select
|
297
|
+
|
298
|
+
def reject
|
299
|
+
klass = self.class.new
|
300
|
+
|
301
|
+
each do |k, v|
|
302
|
+
klass[k] = v unless yield(k, v)
|
303
|
+
end
|
304
|
+
|
305
|
+
klass
|
306
|
+
end
|
307
|
+
|
308
|
+
def reject!
|
309
|
+
each do |k, v|
|
310
|
+
remove_instance_variable "@#{k}" if yield(k, v)
|
311
|
+
end
|
312
|
+
self
|
313
|
+
end
|
314
|
+
|
315
|
+
def inject(init = 0)
|
316
|
+
value = init.dup
|
317
|
+
each do |k, v|
|
318
|
+
val = yield init.dup, [k, v]
|
319
|
+
next if val.nil?
|
320
|
+
value += val
|
321
|
+
end
|
322
|
+
value
|
323
|
+
end
|
324
|
+
alias reduce inject
|
325
|
+
|
326
|
+
def clear
|
327
|
+
each_key do |k|
|
328
|
+
remove_instance_variable "@#{k}"
|
329
|
+
end
|
330
|
+
self
|
331
|
+
end
|
332
|
+
|
333
|
+
def replace(other)
|
334
|
+
h = if other.class == self.class
|
335
|
+
other.to_hash
|
336
|
+
elsif hash? other
|
337
|
+
other
|
338
|
+
else
|
339
|
+
other.to_hash
|
340
|
+
end
|
341
|
+
|
342
|
+
clear
|
343
|
+
wrap h, self
|
344
|
+
end
|
345
|
+
|
346
|
+
def flatten
|
347
|
+
to_h.flatten
|
348
|
+
end
|
349
|
+
|
350
|
+
def has_key?(k)
|
351
|
+
keys.include? k
|
352
|
+
end
|
353
|
+
alias include? has_key?
|
354
|
+
|
355
|
+
def has_keys?(*syms)
|
356
|
+
syms.inject(self) do |klass, sym|
|
357
|
+
val = klass[sym]
|
358
|
+
return false if val.class == self.class && val.blank?
|
359
|
+
klass[sym]
|
360
|
+
end
|
361
|
+
true
|
362
|
+
end
|
363
|
+
|
364
|
+
def exclude?(k)
|
365
|
+
!include? k
|
366
|
+
end
|
367
|
+
|
368
|
+
def sort
|
369
|
+
to_h.sort
|
370
|
+
end
|
371
|
+
|
372
|
+
def shift
|
373
|
+
k = keys.first
|
374
|
+
[k, remove_instance_variable("@#{k}")]
|
375
|
+
end
|
376
|
+
|
377
|
+
def to_a
|
378
|
+
to_h.to_a
|
379
|
+
end
|
380
|
+
alias to_ary to_a
|
381
|
+
|
382
|
+
def compact
|
383
|
+
klass = dup
|
384
|
+
|
385
|
+
klass.each do |k, v|
|
386
|
+
klass.remove_instance_variable("@#{k}") if (v.class == self.class && v.blank?) || v.nil?
|
387
|
+
end
|
388
|
+
|
389
|
+
klass
|
390
|
+
end
|
391
|
+
|
392
|
+
def compact!
|
393
|
+
each do |k, v|
|
394
|
+
remove_instance_variable("@#{k}") if (v.class == self.class && v.blank?) || v.nil?
|
395
|
+
end
|
396
|
+
|
397
|
+
self
|
398
|
+
end
|
399
|
+
|
400
|
+
def deep_compact
|
401
|
+
klass = dup
|
402
|
+
|
403
|
+
klass.each do |k, v|
|
404
|
+
flag = if v.class == self.class
|
405
|
+
klass[k] = v.deep_compact
|
406
|
+
klass[k].present?
|
407
|
+
else
|
408
|
+
!v.nil?
|
409
|
+
end
|
410
|
+
next if flag
|
411
|
+
klass.remove_instance_variable("@#{k}")
|
412
|
+
end
|
413
|
+
|
414
|
+
klass
|
415
|
+
end
|
416
|
+
|
417
|
+
def deep_compact!
|
418
|
+
each do |k, v|
|
419
|
+
flag = if v.class == self.class
|
420
|
+
self[k] = v.deep_compact
|
421
|
+
self[k].present?
|
422
|
+
else
|
423
|
+
!v.nil?
|
424
|
+
end
|
425
|
+
next if flag
|
426
|
+
remove_instance_variable("@#{k}")
|
427
|
+
end
|
428
|
+
|
429
|
+
self
|
430
|
+
end
|
431
|
+
|
432
|
+
def slice(*syms)
|
433
|
+
klass = self.class.new
|
434
|
+
|
435
|
+
each_key do |k|
|
436
|
+
klass[k] = self[k] if syms.map(&:to_sym).include?(k)
|
437
|
+
end
|
438
|
+
|
439
|
+
klass
|
440
|
+
end
|
441
|
+
|
442
|
+
def slice!(*syms)
|
443
|
+
each_key do |k|
|
444
|
+
remove_instance_variable("@#{k}") unless syms.map(&:to_sym).include?(k)
|
445
|
+
end
|
446
|
+
|
447
|
+
self
|
448
|
+
end
|
449
|
+
|
126
450
|
def to_hash
|
127
451
|
deep_hash self
|
128
452
|
end
|
@@ -132,23 +456,24 @@ module Deep
|
|
132
456
|
to_h.to_json
|
133
457
|
end
|
134
458
|
|
459
|
+
private
|
460
|
+
|
135
461
|
def method_missing(method_name, arg = nil)
|
136
462
|
name = method_name.to_s.delete("=")
|
137
463
|
|
138
464
|
if method_name.to_s.end_with? "="
|
139
|
-
keys << name.to_sym unless keys.include? name.to_sym
|
140
465
|
instance_variable_set "@#{name}", hash?(arg) ? wrap(arg) : arg
|
466
|
+
elsif block_given?
|
467
|
+
__send__ "#{name}=", yield
|
141
468
|
else
|
142
469
|
val = instance_variable_get "@#{name}"
|
143
470
|
return val unless val.nil?
|
144
|
-
instance_variable_set "@#{name}", self.class.new
|
471
|
+
instance_variable_set "@#{name}", default.dup || self.class.new
|
145
472
|
end
|
146
473
|
rescue => e
|
147
474
|
super
|
148
475
|
end
|
149
476
|
|
150
|
-
private
|
151
|
-
|
152
477
|
def deep_hash(klass)
|
153
478
|
h = {}
|
154
479
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep-hash-struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- adachi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
version: '0'
|
93
93
|
requirements: []
|
94
94
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.6.
|
95
|
+
rubygems_version: 2.6.11
|
96
96
|
signing_key:
|
97
97
|
specification_version: 4
|
98
98
|
summary: Convenient hash.
|