corefines 1.10.0 → 1.11.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/corefines/hash.rb +66 -0
- data/lib/corefines/version.rb +1 -1
- data/spec/hash/flat_map_spec.rb +61 -0
- data/spec/hash/recurse_spec.rb +36 -0
- data/spec/spec_helper.rb +10 -3
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc488d6deade84992853796d2e3e315e23a2bb32
|
4
|
+
data.tar.gz: 4f671bc5963d4002509d54a90dc41024a9efa676
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96553f167a0dc42ce8c556ef92e3542940bd6093ab1b5e368c58e7627e3f83ed479368bc5b552be845ee84c68ee52e254781ab42eb44777ad53d75e20c19108f
|
7
|
+
data.tar.gz: 5ca6dc072b0ecf10503271b7d18ab2bee23efdf1663050f59a9c38e5c68409a19636ea9979986542848f11a960132361575e3b5142fdf225525b27e559ab3986
|
data/lib/corefines/hash.rb
CHANGED
@@ -69,6 +69,43 @@ module Corefines
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
##
|
73
|
+
# @!method flat_map(&block)
|
74
|
+
# Returns a new hash with the merged results of running the _block_ once
|
75
|
+
# for every entry in +self+.
|
76
|
+
#
|
77
|
+
# @example
|
78
|
+
# hash = { a: 1, b: 2, c: 3 }
|
79
|
+
# hash.flat_map { |k, v| {k => v * 2, k.upcase => v} if v % 2 == 1 }
|
80
|
+
# # => { a: 2, A: 1, c: 6, C: 3 }
|
81
|
+
# hash.flat_map { |k, v| [[k, v * 2], [k.upcase => v]] if v % 2 == 1 }
|
82
|
+
# # => { a: 2, A: 1, c: 6, C: 3 }
|
83
|
+
#
|
84
|
+
# @yield [key, value] gives every key-value pair to the block.
|
85
|
+
# @yieldreturn [#to_h, Array, nil] an object that will be interpreted as
|
86
|
+
# a Hash and merged into the result, or nil to omit this key-value.
|
87
|
+
# @return [Hash] a new hash.
|
88
|
+
module FlatMap
|
89
|
+
refine ::Hash do
|
90
|
+
def flat_map
|
91
|
+
each_with_object({}) do |(key, value), hash|
|
92
|
+
yielded = yield(key, value)
|
93
|
+
|
94
|
+
if yielded.is_a? ::Hash
|
95
|
+
hash.merge!(yielded)
|
96
|
+
elsif yielded.is_a? ::Array
|
97
|
+
# Array#to_h exists since Ruby 2.1.
|
98
|
+
yielded.each do |pair|
|
99
|
+
hash.store(*pair)
|
100
|
+
end
|
101
|
+
elsif yielded
|
102
|
+
hash.merge!(yielded.to_h)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
72
109
|
##
|
73
110
|
# @!method only(*keys)
|
74
111
|
# @example
|
@@ -132,6 +169,35 @@ module Corefines
|
|
132
169
|
end
|
133
170
|
end
|
134
171
|
|
172
|
+
##
|
173
|
+
# @!method recurse(&block)
|
174
|
+
# Transforms this hash and each of its sub-hashes recursively using the
|
175
|
+
# given _block_.
|
176
|
+
#
|
177
|
+
# It does not mutate the hash if the given _block_ is pure (i.e. does not
|
178
|
+
# modify given hashes, but returns new ones).
|
179
|
+
#
|
180
|
+
# @example
|
181
|
+
# hash = {"a" => 1, "b" => {"c" => {"e" => 5}, "d" => 4}}
|
182
|
+
# hash.recurse!(&:symbolize_keys!) # => {a: 1, b: {c: {e: 5}, d: 4}}
|
183
|
+
# hash # => {a: 1, b: {c: {e: 5}, d: 4}}
|
184
|
+
#
|
185
|
+
# @yield [Hash] gives this hash and every sub-hash (recursively).
|
186
|
+
# The return value replaces the old value.
|
187
|
+
# @return [Hash] a result of applying _block_ to this hash and each of
|
188
|
+
# its sub-hashes (recursively).
|
189
|
+
#
|
190
|
+
module Recurse
|
191
|
+
refine ::Hash do
|
192
|
+
def recurse(&block)
|
193
|
+
h = yield(self)
|
194
|
+
h.each do |key, value|
|
195
|
+
h[key] = value.recurse(&block) if value.is_a? ::Hash
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
135
201
|
##
|
136
202
|
# @!method rekey(key_map = nil, &block)
|
137
203
|
# Returns a new hash with keys transformed according to the given
|
data/lib/corefines/version.rb
CHANGED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
describe '#flat_map' do
|
5
|
+
using Corefines::Hash::flat_map
|
6
|
+
|
7
|
+
let(:hash) { {a: 1, b: 2, c: 3} }
|
8
|
+
let!(:original) { hash.dup }
|
9
|
+
|
10
|
+
context "with block" do
|
11
|
+
it "returns a new hash, does not mutate self" do
|
12
|
+
expect( hash.flat_map { |k, v| {k => v * 2} } ).to be_a Hash
|
13
|
+
expect( hash ).to eq original
|
14
|
+
end
|
15
|
+
|
16
|
+
context "that yields Hash" do
|
17
|
+
it "returns merged results of running block for each entry" do
|
18
|
+
expect( hash.flat_map { |k, v| {k => v * 2, k.upcase => v * 3} } )
|
19
|
+
.to eq({a: 2, A: 3, b: 4, B: 6, c: 6, C: 9})
|
20
|
+
end
|
21
|
+
|
22
|
+
it "does not flatten yielded hashes" do
|
23
|
+
expect( hash.flat_map { |k, v| {k => {k.upcase => v}} } )
|
24
|
+
.to eq({a: {A: 1}, b: {B: 2}, c: {C: 3}})
|
25
|
+
end
|
26
|
+
|
27
|
+
it "omits entries for which the block yielded nil" do
|
28
|
+
expect( hash.flat_map { |k, v| {k.upcase => v * 2} if k != :b } )
|
29
|
+
.to eq({A: 2, C: 6})
|
30
|
+
end
|
31
|
+
|
32
|
+
it "handles duplicated keys by method the last wins" do
|
33
|
+
expect( hash.flat_map { |k, v| {k => v * 2, b: v * 6} } )
|
34
|
+
.to eq({a: 2, b: 18, c: 6})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "that yields Array" do
|
39
|
+
it "interprets array of pairs as Hash" do
|
40
|
+
expect( hash.flat_map { |k, v| [[k, v * 2], [k.upcase, v * 3]] } )
|
41
|
+
.to eq({a: 2, A: 3, b: 4, B: 6, c: 6, C: 9})
|
42
|
+
end
|
43
|
+
|
44
|
+
it "raises ArgumentError if nested array has more than 2 elements" do
|
45
|
+
expect { hash.flat_map { |k, v| [[k, v, v]] } }.to raise_error(ArgumentError)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# There's no usable class in 1.9.3 implementing #to_h and I'd like to
|
50
|
+
# keep this simple...
|
51
|
+
if RUBY_VERSION.to_f >= 2
|
52
|
+
context "that yields object responding to #to_h" do
|
53
|
+
it "calls #to_h on yielded value" do
|
54
|
+
expect( hash.flat_map { |k, v| OpenStruct.new(k => v * 2) } )
|
55
|
+
.to eq({a: 2, b: 4, c: 6})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe Hash do
|
2
|
+
describe '#recurse' do
|
3
|
+
using Corefines::Hash::recurse
|
4
|
+
|
5
|
+
subject(:hash) { {a: 1, b: {d: {f: 6}, e: 5}, c: 3} }
|
6
|
+
let(:expected) { {a: 1, b: {d: {f: 6, x: 42}, e: 5, x: 42}, c: 3, x: 42} }
|
7
|
+
let!(:original) { Marshal.load(Marshal.dump(hash)) } # deep clone
|
8
|
+
|
9
|
+
shared_examples :common do
|
10
|
+
it "returns a result of calling block on the hash and sub-hashes recursively" do
|
11
|
+
is_expected.to eq expected
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with pure block" do
|
16
|
+
subject!(:result) { hash.recurse { |h| h.merge(x: 42) } }
|
17
|
+
|
18
|
+
include_examples :common
|
19
|
+
|
20
|
+
it "does not mutate the original hash" do
|
21
|
+
expect( hash ).to eq original
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with impure block" do
|
26
|
+
subject!(:result) { hash.recurse { |h| h.merge!(x: 42) } }
|
27
|
+
|
28
|
+
include_examples :common
|
29
|
+
|
30
|
+
it "modifies the hash in-place" do
|
31
|
+
expect( hash ).to eq expected
|
32
|
+
expect( hash ).to_not eq original
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'simplecov' unless RUBY_ENGINE == 'jruby'
|
2
|
-
require 'corefines'
|
3
|
-
|
4
1
|
RSpec.configure do |config|
|
5
2
|
|
6
3
|
# rspec-expectations config
|
@@ -28,3 +25,13 @@ RSpec.configure do |config|
|
|
28
25
|
|
29
26
|
config.color = true
|
30
27
|
end
|
28
|
+
|
29
|
+
unless RUBY_ENGINE == 'jruby'
|
30
|
+
require 'simplecov'
|
31
|
+
|
32
|
+
SimpleCov.start do
|
33
|
+
add_filter '/spec/'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'corefines'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: corefines
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jakub Jirutka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
33
|
+
version: '1.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0
|
40
|
+
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,8 +128,10 @@ files:
|
|
128
128
|
- spec/enumerable/map_to_spec.rb
|
129
129
|
- spec/hash/compact_spec.rb
|
130
130
|
- spec/hash/except_spec.rb
|
131
|
+
- spec/hash/flat_map_spec.rb
|
131
132
|
- spec/hash/only_spec.rb
|
132
133
|
- spec/hash/op_add_spec.rb
|
134
|
+
- spec/hash/recurse_spec.rb
|
133
135
|
- spec/hash/rekey_spec.rb
|
134
136
|
- spec/hash/symbolize_keys_spec.rb
|
135
137
|
- spec/module/alias_class_method_spec.rb
|
@@ -179,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
181
|
version: '0'
|
180
182
|
requirements: []
|
181
183
|
rubyforge_project:
|
182
|
-
rubygems_version: 2.6.
|
184
|
+
rubygems_version: 2.6.13
|
183
185
|
signing_key:
|
184
186
|
specification_version: 4
|
185
187
|
summary: A collection of refinements for Ruby core classes.
|