mimi-core 1.0.0 → 1.1.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/lib/mimi/core/core_ext.rb +169 -9
- data/lib/mimi/core/struct.rb +56 -0
- data/lib/mimi/core/version.rb +1 -1
- data/lib/mimi/core.rb +2 -0
- data/mimi-core.gemspec +0 -2
- metadata +3 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db5931bbbdf22818f96d2979dac52cbc4d4058ed
|
4
|
+
data.tar.gz: d8b666e59ec1d340233f7b9a95ca7624dc06b22d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbc4fe8b0d0150fc7181d050de3c037885f90a85c12a4fa55d6e00339151a7adf93506f44026533f91ab6a9f90132a79b72ae463bd5fbe696df8ae17c6a66aad
|
7
|
+
data.tar.gz: 0b5e725a4844406bf1cefbd98c1e7f3bee2a358195c4041dcb0f8cf4e00b5059905845d22ef08543e663725b84e045d643d648656c78fbb0ab0e46dda4eaf040
|
data/lib/mimi/core/core_ext.rb
CHANGED
@@ -1,13 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'hashie'
|
4
|
-
|
5
3
|
class Hash
|
6
4
|
unless instance_methods(false).include?(:only)
|
5
|
+
#
|
6
|
+
# Returns a Hash with only given keys, if present
|
7
|
+
#
|
8
|
+
# @param *keys [*] list of keys
|
9
|
+
# @return [Hash] a new Hash
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# h = { a: 1, b: 2, :c 3 }
|
13
|
+
# h.only(:a, :b, :d) # => { a: 1, b: 2 }
|
14
|
+
#
|
7
15
|
def only(*keys)
|
8
16
|
dup.only!(*keys)
|
9
17
|
end
|
10
18
|
|
19
|
+
# Modifies the Hash keeping only given keys, if present
|
20
|
+
#
|
21
|
+
# @param *keys [*] list of keys
|
22
|
+
# @return [Hash] self
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# h = { a: 1, b: 2, :c 3 }
|
26
|
+
# h.only!(:a, :b, :d)
|
27
|
+
# h # => { a: 1, b: 2 }
|
28
|
+
#
|
11
29
|
def only!(*keys)
|
12
30
|
if keys.size == 1 && keys.first.is_a?(Array)
|
13
31
|
raise ArgumentError, 'Hash#only!() expects keys as list of arguments,' \
|
@@ -19,10 +37,30 @@ class Hash
|
|
19
37
|
end
|
20
38
|
|
21
39
|
unless instance_methods(false).include?(:except)
|
40
|
+
#
|
41
|
+
# Returns a Hash with given keys excluded, if present
|
42
|
+
#
|
43
|
+
# @param *keys [*] list of keys
|
44
|
+
# @return [Hash] a new Hash
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# h = { a: 1, b: 2, :c 3 }
|
48
|
+
# h.except(:a, :b, :d) # => { c: 3 }
|
49
|
+
#
|
22
50
|
def except(*keys)
|
23
51
|
dup.except!(*keys)
|
24
52
|
end
|
25
53
|
|
54
|
+
# Modifies the Hash excluding given keys, if present
|
55
|
+
#
|
56
|
+
# @param *keys [*] list of keys
|
57
|
+
# @return [Hash] self
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# h = { a: 1, b: 2, :c 3 }
|
61
|
+
# h.except!(:a, :b, :d)
|
62
|
+
# h # => { c: 3 }
|
63
|
+
#
|
26
64
|
def except!(*keys)
|
27
65
|
if keys.size == 1 && keys.first.is_a?(Array)
|
28
66
|
raise ArgumentError, 'Hash#except!() expects keys as list of arguments,' \
|
@@ -34,10 +72,51 @@ class Hash
|
|
34
72
|
end
|
35
73
|
|
36
74
|
unless instance_methods(false).include?(:deep_merge)
|
37
|
-
|
75
|
+
#
|
76
|
+
# Deep merges self (left) Hash with another Hash
|
77
|
+
#
|
78
|
+
# On keys existing in both Hashes:
|
79
|
+
# * merges Hash values by merging left Hash with the right Hash
|
80
|
+
# * merges Array values by union operator
|
81
|
+
# * for other values overwrites left Hash value with the right Hash value
|
82
|
+
#
|
83
|
+
# @param right [Hash] the right (other) Hash
|
84
|
+
# @return [Hash] self
|
85
|
+
#
|
86
|
+
def deep_merge!(right)
|
87
|
+
right.each do |k ,v|
|
88
|
+
unless self.key?(k)
|
89
|
+
self[k] = v
|
90
|
+
next
|
91
|
+
end
|
92
|
+
if self[k].is_a?(Hash) && v.is_a?(Hash)
|
93
|
+
self[k].deep_merge!(v)
|
94
|
+
elsif self[k].is_a?(Array) && v.is_a?(Array)
|
95
|
+
self[k] = self[k] | v
|
96
|
+
else
|
97
|
+
# unmergeable values, overwrite
|
98
|
+
self[k] = v
|
99
|
+
end
|
100
|
+
end
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
# @see #deep_merge!
|
105
|
+
#
|
106
|
+
# @param right [Hash] the right (other) Hash
|
107
|
+
# @return [Hash] a new Hash
|
108
|
+
#
|
109
|
+
def deep_merge(right)
|
110
|
+
deep_dup.deep_merge!(right)
|
111
|
+
end
|
38
112
|
end
|
39
113
|
|
40
114
|
unless instance_methods(false).include?(:deep_dup)
|
115
|
+
#
|
116
|
+
# Duplicates a Hash with all nested values
|
117
|
+
#
|
118
|
+
# @return [Hash] a new Hash
|
119
|
+
#
|
41
120
|
def deep_dup
|
42
121
|
map do |k, v|
|
43
122
|
v = v.respond_to?(:deep_dup) ? v.deep_dup : v.dup
|
@@ -47,6 +126,11 @@ class Hash
|
|
47
126
|
end
|
48
127
|
|
49
128
|
unless instance_methods(false).include?(:symbolize_keys)
|
129
|
+
#
|
130
|
+
# Symbolizes Hash keys
|
131
|
+
#
|
132
|
+
# @return [Hash] a new Hash
|
133
|
+
#
|
50
134
|
def symbolize_keys
|
51
135
|
map do |k, v|
|
52
136
|
k = k.respond_to?(:to_sym) ? k.to_sym : k
|
@@ -54,12 +138,21 @@ class Hash
|
|
54
138
|
end.to_h
|
55
139
|
end
|
56
140
|
|
141
|
+
# Modifies the Hash symbolizing its keys
|
142
|
+
#
|
143
|
+
# @return [Hash] self
|
144
|
+
#
|
57
145
|
def symbolize_keys!
|
58
146
|
replace(symbolize_keys)
|
59
147
|
end
|
60
148
|
end
|
61
149
|
|
62
150
|
unless instance_methods(false).include?(:deep_symbolize_keys)
|
151
|
+
#
|
152
|
+
# Symbolizes Hash keys including all nested Hashes
|
153
|
+
#
|
154
|
+
# @return [Hash] a new Hash
|
155
|
+
#
|
63
156
|
def deep_symbolize_keys
|
64
157
|
map do |k, v|
|
65
158
|
k = k.respond_to?(:to_sym) ? k.to_sym : k
|
@@ -68,12 +161,21 @@ class Hash
|
|
68
161
|
end.to_h
|
69
162
|
end
|
70
163
|
|
164
|
+
# Modifies the Hash symbolizing its keys including all nested Hashes
|
165
|
+
#
|
166
|
+
# @return [Hash] self
|
167
|
+
#
|
71
168
|
def deep_symbolize_keys!
|
72
169
|
replace(deep_symbolize_keys)
|
73
170
|
end
|
74
171
|
end
|
75
172
|
|
76
173
|
unless instance_methods(false).include?(:stringify_keys)
|
174
|
+
#
|
175
|
+
# Stringifies Hash keys
|
176
|
+
#
|
177
|
+
# @return [Hash] a new Hash
|
178
|
+
#
|
77
179
|
def stringify_keys
|
78
180
|
map do |k, v|
|
79
181
|
k = k.respond_to?(:to_s) ? k.to_s : k
|
@@ -81,12 +183,21 @@ class Hash
|
|
81
183
|
end.to_h
|
82
184
|
end
|
83
185
|
|
186
|
+
# Modifies the Hash stringifying its keys
|
187
|
+
#
|
188
|
+
# @return [Hash] self
|
189
|
+
#
|
84
190
|
def stringify_keys!
|
85
191
|
replace(stringify_keys)
|
86
192
|
end
|
87
193
|
end
|
88
194
|
|
89
195
|
unless instance_methods(false).include?(:deep_stringify_keys)
|
196
|
+
#
|
197
|
+
# Stringifies Hash keys including all nested Hashes
|
198
|
+
#
|
199
|
+
# @return [Hash] a new Hash
|
200
|
+
#
|
90
201
|
def deep_stringify_keys
|
91
202
|
map do |k, v|
|
92
203
|
k = k.respond_to?(:to_s) ? k.to_s : k
|
@@ -95,6 +206,10 @@ class Hash
|
|
95
206
|
end.to_h
|
96
207
|
end
|
97
208
|
|
209
|
+
# Modifies the Hash stringifying its keys including all nested Hashes
|
210
|
+
#
|
211
|
+
# @return [Hash] self
|
212
|
+
#
|
98
213
|
def deep_stringify_keys!
|
99
214
|
replace(deep_stringify_keys)
|
100
215
|
end
|
@@ -103,25 +218,65 @@ end
|
|
103
218
|
|
104
219
|
class Array
|
105
220
|
unless instance_methods(false).include?(:only)
|
106
|
-
|
107
|
-
|
221
|
+
#
|
222
|
+
# Returns an Array with only selected values, if present
|
223
|
+
#
|
224
|
+
# @param *values [*] list of values
|
225
|
+
# @return [Array] a new Array
|
226
|
+
#
|
227
|
+
# @example
|
228
|
+
# a = [:a, :b, :c]
|
229
|
+
# a.only(:a, :b, :d) # => [:a, :b]
|
230
|
+
#
|
231
|
+
def only(*values)
|
232
|
+
dup.only!(*values)
|
108
233
|
end
|
109
234
|
|
110
|
-
|
111
|
-
|
112
|
-
|
235
|
+
# Modifies the Array keeping only given values, if present
|
236
|
+
#
|
237
|
+
# @param *values [*] list of values
|
238
|
+
# @return [Array] self
|
239
|
+
#
|
240
|
+
# @example
|
241
|
+
# a = [:a, :b, :c]
|
242
|
+
# a.only!(:a, :b, :d)
|
243
|
+
# a # => [:a, :b]
|
244
|
+
#
|
245
|
+
def only!(*values)
|
246
|
+
if values.size == 1 && values.first.is_a?(Array)
|
247
|
+
raise ArgumentError, 'Array#only!() expects values as list of arguments,' \
|
113
248
|
' not an Array as first argument'
|
114
249
|
end
|
115
|
-
select! { |k|
|
250
|
+
select! { |k| values.include?(k) }
|
116
251
|
self
|
117
252
|
end
|
118
253
|
end
|
119
254
|
|
120
255
|
unless instance_methods(false).include?(:except)
|
256
|
+
#
|
257
|
+
# Returns an Array with given values excluded, if present
|
258
|
+
#
|
259
|
+
# @param *values [*] list of values
|
260
|
+
# @return [Array] a new Array
|
261
|
+
#
|
262
|
+
# @example
|
263
|
+
# a = [:a, :b, :c]
|
264
|
+
# a.except(:a, :b, :d) # => [:c]
|
265
|
+
#
|
121
266
|
def except(*keys)
|
122
267
|
dup.except!(*keys)
|
123
268
|
end
|
124
269
|
|
270
|
+
# Modifies the Array excluding given values, if present
|
271
|
+
#
|
272
|
+
# @param *values [*] list of values
|
273
|
+
# @return [Array] self
|
274
|
+
#
|
275
|
+
# @example
|
276
|
+
# a = [:a, :b, :c]
|
277
|
+
# a.except!(:a, :b, :d)
|
278
|
+
# a # => [:c]
|
279
|
+
#
|
125
280
|
def except!(*keys)
|
126
281
|
if keys.size == 1 && keys.first.is_a?(Array)
|
127
282
|
raise ArgumentError, 'Array#except!() expects keys as list of arguments,' \
|
@@ -133,6 +288,11 @@ class Array
|
|
133
288
|
end
|
134
289
|
|
135
290
|
unless instance_methods(false).include?(:deep_dup)
|
291
|
+
#
|
292
|
+
# Duplicates an Array with all nested values
|
293
|
+
#
|
294
|
+
# @return [Hash] a new Hash
|
295
|
+
#
|
136
296
|
def deep_dup
|
137
297
|
map do |v|
|
138
298
|
v.respond_to?(:deep_dup) ? v.deep_dup : v.dup
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mimi
|
4
|
+
module Core
|
5
|
+
#
|
6
|
+
# Mimi::Core::Struct is a simple immutable data structure.
|
7
|
+
#
|
8
|
+
# It allows instantiating an object from a set of attributes and makes them
|
9
|
+
# available as object methods and Hash paramaters:
|
10
|
+
# my_object = Mimi::Core::Struct.new(a: 1, b: 2)
|
11
|
+
#
|
12
|
+
# my_object.a # => 1
|
13
|
+
# my_object[:a] # => 1
|
14
|
+
# my_object['a'] # => 1
|
15
|
+
#
|
16
|
+
# It only allows access to defined attributes:
|
17
|
+
# my_object.c # => NoMethodError
|
18
|
+
# my_object[:c] # => NameError
|
19
|
+
#
|
20
|
+
class Struct
|
21
|
+
#
|
22
|
+
# Creates a Struct object from a set of attributes
|
23
|
+
#
|
24
|
+
# @param attrs [Hash]
|
25
|
+
#
|
26
|
+
def initialize(attrs = {})
|
27
|
+
raise ArgumentError, "Hash is expected as attrs" unless attrs.is_a?(Hash)
|
28
|
+
@attributes = attrs.map { |k, v| [k.to_sym, v.dup] }.to_h
|
29
|
+
@attributes.keys.each do |attr_name|
|
30
|
+
define_singleton_method(attr_name) { self[attr_name] }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Fetches attribute by its name
|
35
|
+
#
|
36
|
+
# @param name [String,Symbol]
|
37
|
+
# @return [Object] attribute's value
|
38
|
+
#
|
39
|
+
def [](attr_name)
|
40
|
+
attr_name = attr_name.to_sym
|
41
|
+
unless @attributes.key?(attr_name)
|
42
|
+
raise NameError, "undefined attribute #{attr_name.inspect}"
|
43
|
+
end
|
44
|
+
@attributes[attr_name]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns Struct attributes as a Hash
|
48
|
+
#
|
49
|
+
# @return [Hash]
|
50
|
+
#
|
51
|
+
def to_h
|
52
|
+
@attributes
|
53
|
+
end
|
54
|
+
end # class Struct
|
55
|
+
end # module Core
|
56
|
+
end # module Mimi
|
data/lib/mimi/core/version.rb
CHANGED
data/lib/mimi/core.rb
CHANGED
data/mimi-core.gemspec
CHANGED
@@ -27,8 +27,6 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
-
spec.add_dependency 'hashie', '~> 3.6'
|
31
|
-
|
32
30
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
33
31
|
spec.add_development_dependency 'pry', '~> 0.10'
|
34
32
|
spec.add_development_dependency 'rake', '~> 10.0'
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mimi-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Kukushkin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: hashie
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '3.6'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '3.6'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,6 +90,7 @@ files:
|
|
104
90
|
- lib/mimi/core/manifest.rb
|
105
91
|
- lib/mimi/core/module.rb
|
106
92
|
- lib/mimi/core/rake.rb
|
93
|
+
- lib/mimi/core/struct.rb
|
107
94
|
- lib/mimi/core/version.rb
|
108
95
|
- mimi-core.gemspec
|
109
96
|
homepage: https://github.com/kukushkin/mimi-core
|