darthjee-core_ext 1.5.6 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +14 -0
- data/.rubocop.yml +17 -0
- data/.rubocop_todo.yml +12 -0
- data/Gemfile +2 -1
- data/Rakefile +2 -0
- data/core_ext.gemspec +6 -3
- data/lib/darthjee/core_ext/array/hash_builder.rb +21 -13
- data/lib/darthjee/core_ext/array.rb +4 -2
- data/lib/darthjee/core_ext/date.rb +2 -0
- data/lib/darthjee/core_ext/enumerable.rb +5 -3
- data/lib/darthjee/core_ext/hash/chain_fetcher.rb +33 -0
- data/lib/darthjee/core_ext/hash/deep_hash_constructor.rb +62 -60
- data/lib/darthjee/core_ext/hash/key_changer.rb +64 -54
- data/lib/darthjee/core_ext/hash/keys_sorter.rb +31 -0
- data/lib/darthjee/core_ext/hash/squasher.rb +31 -0
- data/lib/darthjee/core_ext/hash/to_hash_mapper.rb +21 -0
- data/lib/darthjee/core_ext/hash/value_changer.rb +48 -44
- data/lib/darthjee/core_ext/hash.rb +28 -58
- data/lib/darthjee/core_ext/math.rb +4 -2
- data/lib/darthjee/core_ext/numeric.rb +5 -3
- data/lib/darthjee/core_ext/object/default_value.rb +2 -1
- data/lib/darthjee/core_ext/object.rb +2 -0
- data/lib/darthjee/core_ext/symbol.rb +2 -0
- data/lib/darthjee/core_ext/time.rb +2 -0
- data/lib/darthjee/core_ext/version.rb +3 -1
- data/lib/darthjee/core_ext.rb +2 -0
- data/lib/darthjee.rb +2 -1
- data/spec/lib/array_spec.rb +27 -19
- data/spec/lib/date_spec.rb +2 -0
- data/spec/lib/enumerable_spec.rb +10 -8
- data/spec/lib/hash/chain_fetcher_spec.rb +11 -0
- data/spec/lib/hash/deep_hash_constructor_spec.rb +3 -1
- data/spec/lib/hash/key_changer_spec.rb +19 -5
- data/spec/lib/hash/keys_sorter_spec.rb +10 -0
- data/spec/lib/hash/squasher_spec.rb +9 -0
- data/spec/lib/hash/to_hash_mapper_spec.rb +10 -0
- data/spec/lib/hash_spec.rb +16 -46
- data/spec/lib/math_spec.rb +2 -0
- data/spec/lib/numeric_spec.rb +2 -0
- data/spec/lib/object/default_value_spe.rb +2 -0
- data/spec/lib/object_spec.rb +2 -0
- data/spec/lib/symbol_spec.rb +2 -0
- data/spec/lib/time_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/models/default_value.rb +2 -0
- data/spec/support/models/hash/value_changer/dummy.rb +19 -13
- data/spec/support/models/hash/value_changer/dummy_iteractor.rb +13 -8
- data/spec/support/shared_examples/{array_random.rb → array/array_random.rb} +5 -2
- data/spec/support/shared_examples/clean.rb +14 -2
- data/spec/support/shared_examples/date.rb +2 -0
- data/spec/support/shared_examples/expected.rb +2 -1
- data/spec/support/shared_examples/{chain_fetch.rb → hash/chain_fetch.rb} +9 -7
- data/spec/support/shared_examples/{chain_hash_keys_changer.rb → hash/chain_hash_keys_changer.rb} +14 -11
- data/spec/support/shared_examples/{hash_keys_changer.rb → hash/hash_keys_changer.rb} +7 -5
- data/spec/support/shared_examples/hash/hash_squasher.rb +23 -0
- data/spec/support/shared_examples/{hash_transpose.rb → hash/hash_transpose.rb} +8 -6
- data/spec/support/shared_examples/hash/keys_appender.rb +69 -0
- data/spec/support/shared_examples/{keys_camelizer.rb → hash/keys_camelizer.rb} +6 -4
- data/spec/support/shared_examples/hash/keys_sorter.rb +67 -0
- data/spec/support/shared_examples/{keys_underscorer.rb → hash/keys_underscorer.rb} +4 -3
- data/spec/support/shared_examples/{map_to_hash.rb → hash/map_to_hash.rb} +16 -16
- data/spec/support/shared_examples/{remap.rb → hash/remap.rb} +16 -13
- data/spec/support/shared_examples/hash/value_changer.rb +192 -0
- metadata +76 -30
- data/circle.yml +0 -10
- data/spec/support/shared_examples/keys_appender.rb +0 -43
- data/spec/support/shared_examples/value_changer.rb +0 -147
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f91f602918068826bc0e97f7e555f680226b429c
|
4
|
+
data.tar.gz: ccb555082fd2cc831024d1f9b565f6ca2dcf543a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11af6fe53de559202c101a5809ccbeca632c8daaba4a49d8a7415a75885f697d378bbd970607ee89f5d26ec145d1309875b0f20d2fa2abbca2f7ba55eadcbe01
|
7
|
+
data.tar.gz: 874149c8200c544b455efce3302aba8a720794272457b72dcb0353d9d05df68441a26753f9a368a082d92a1cf23947791894aee76aba280c039eb3159805d2f5
|
@@ -0,0 +1,14 @@
|
|
1
|
+
version: 2
|
2
|
+
jobs:
|
3
|
+
build:
|
4
|
+
docker:
|
5
|
+
- image: circleci/ruby:2.4.1
|
6
|
+
steps:
|
7
|
+
- checkout
|
8
|
+
- run: curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
9
|
+
- run: chmod +x ./cc-test-reporter
|
10
|
+
- run: ./cc-test-reporter before-build
|
11
|
+
- run: bundle install
|
12
|
+
- run: bundle exec rspec
|
13
|
+
- run: rubocop
|
14
|
+
- run: ./cc-test-reporter after-build --exit-code $?
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
TargetRubyVersion: 2.4
|
5
|
+
|
6
|
+
Naming/PredicateName:
|
7
|
+
Exclude:
|
8
|
+
- 'lib/darthjee/core_ext/object.rb'
|
9
|
+
|
10
|
+
Metrics/ClassLength:
|
11
|
+
Exclude:
|
12
|
+
- 'lib/darthjee/core_ext/hash.rb'
|
13
|
+
|
14
|
+
Metrics/BlockLength:
|
15
|
+
Exclude:
|
16
|
+
- 'spec/**/*_spec.rb'
|
17
|
+
- 'spec/support/shared_*/**/*.rb'
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2018-07-26 20:39:06 +0000 using RuboCop version 0.58.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 16
|
10
|
+
Style/Documentation:
|
11
|
+
Enabled: false
|
12
|
+
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/core_ext.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'darthjee/core_ext/version'
|
5
6
|
|
@@ -20,8 +21,10 @@ Gem::Specification.new do |gem|
|
|
20
21
|
gem.add_runtime_dependency 'activesupport', '>= 5.x'
|
21
22
|
|
22
23
|
gem.add_development_dependency 'bundler', '~> 1.6'
|
24
|
+
gem.add_development_dependency 'pry-nav', '~> 0.2.4'
|
23
25
|
gem.add_development_dependency 'rake', '>= 12.3.1'
|
24
26
|
gem.add_development_dependency 'rspec', '>= 3.7'
|
25
|
-
gem.add_development_dependency '
|
27
|
+
gem.add_development_dependency 'rubocop'
|
26
28
|
gem.add_development_dependency 'simplecov', '~> 0.14.1'
|
29
|
+
gem.add_development_dependency 'yard'
|
27
30
|
end
|
@@ -1,20 +1,28 @@
|
|
1
|
-
|
2
|
-
attr_accessor :values, :keys
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
3
|
+
class Array
|
4
|
+
class HashBuilder
|
5
|
+
attr_accessor :values, :keys
|
8
6
|
|
9
|
-
|
10
|
-
|
7
|
+
def initialize(values, keys)
|
8
|
+
@values = values.dup
|
9
|
+
@keys = keys.dup
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
def build
|
13
|
+
fixes_sizes
|
14
|
+
|
15
|
+
Hash[[keys, values].transpose]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
14
19
|
|
15
|
-
|
20
|
+
def fixes_sizes
|
21
|
+
values.concat Array.new(keys.size - values.size) if needs_resizing?
|
22
|
+
end
|
16
23
|
|
17
|
-
|
18
|
-
|
24
|
+
def needs_resizing?
|
25
|
+
keys.size > values.size
|
26
|
+
end
|
19
27
|
end
|
20
28
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Array
|
2
|
-
autoload :HashBuilder,
|
4
|
+
autoload :HashBuilder, 'darthjee/core_ext/array/hash_builder'
|
3
5
|
|
4
6
|
def mapk(*keys)
|
5
7
|
keys.inject(self) do |enum, key|
|
@@ -39,6 +41,6 @@ class Array
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def random!
|
42
|
-
|
44
|
+
slice!(rand(size))
|
43
45
|
end
|
44
46
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Enumerable
|
2
4
|
def clean
|
3
5
|
deep_dup.clean!
|
@@ -38,8 +40,8 @@ module Enumerable
|
|
38
40
|
|
39
41
|
private
|
40
42
|
|
41
|
-
def empty_value?(
|
42
|
-
|
43
|
-
((
|
43
|
+
def empty_value?(value)
|
44
|
+
value.nil? || value.try(:empty?) ||
|
45
|
+
((value.is_a?(Hash) || value.is_a?(Array)) && value.clean!.empty?)
|
44
46
|
end
|
45
47
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
class ChainFetcher
|
5
|
+
def initialize(hash, *keys, &block)
|
6
|
+
@hash = hash
|
7
|
+
@keys = keys
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch
|
12
|
+
block.present? ? fetch_with_block : fetch_without_block
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :hash, :keys, :block
|
18
|
+
|
19
|
+
def fetch_with_block
|
20
|
+
@hash = hash.fetch(keys.shift) do |*args|
|
21
|
+
missed_keys = keys
|
22
|
+
@keys = []
|
23
|
+
block.call(*(args + [missed_keys]))
|
24
|
+
end until keys.empty?
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch_without_block
|
29
|
+
@hash = hash.fetch(keys.shift) until keys.empty?
|
30
|
+
hash
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,83 +1,85 @@
|
|
1
|
-
|
2
|
-
attr_accessor :separator
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
class Hash
|
4
|
+
class DeepHashConstructor
|
5
|
+
attr_accessor :separator
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
array_deep_hash(object)
|
11
|
-
elsif object.is_a? Hash
|
12
|
-
hash_deep_hash(object)
|
13
|
-
else
|
14
|
-
object
|
7
|
+
def initialize(separator)
|
8
|
+
@separator = separator
|
15
9
|
end
|
16
|
-
end
|
17
10
|
|
18
|
-
|
11
|
+
def deep_hash(object)
|
12
|
+
if object.is_a? Array
|
13
|
+
array_deep_hash(object)
|
14
|
+
elsif object.is_a? Hash
|
15
|
+
hash_deep_hash(object)
|
16
|
+
else
|
17
|
+
object
|
18
|
+
end
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
array.map { |v| v.is_a?(Hash) ? deep_hash(v) : v }
|
22
|
-
end
|
21
|
+
private
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
base_key, child_key = split_key(k, separator)
|
28
|
-
set_deep_hash_positioned_value(new_hash, base_key, v, child_key)
|
29
|
-
end
|
23
|
+
def array_deep_hash(array)
|
24
|
+
array.map { |v| v.is_a?(Hash) ? deep_hash(v) : v }
|
25
|
+
end
|
30
26
|
|
31
|
-
|
32
|
-
|
27
|
+
def hash_deep_hash(hash)
|
28
|
+
{}.tap do |new_hash|
|
29
|
+
hash.each do |k, v|
|
30
|
+
base_key, child_key = split_key(k, separator)
|
31
|
+
set_deep_hash_positioned_value(new_hash, base_key, v, child_key)
|
32
|
+
end
|
33
|
+
|
34
|
+
new_hash.each do |k, v|
|
35
|
+
new_hash[k] = deep_hash(v)
|
36
|
+
end
|
33
37
|
end
|
34
38
|
end
|
35
|
-
end
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
def split_key(key, separator)
|
41
|
+
separator_rxp = separator == '.' ? "\\#{separator}" : separator
|
42
|
+
skipper = "[^#{separator}]"
|
43
|
+
regexp = Regexp.new("^(#{skipper}*)#{separator_rxp}(.*)")
|
44
|
+
match = key.match(regexp)
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
match ? match[1..2] : key
|
47
|
+
end
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
def set_deep_hash_array_value(hash, base_key, index, value, key = nil)
|
50
|
+
key_without_index = base_key.gsub("[#{index}]", '')
|
51
|
+
hash[key_without_index] ||= []
|
49
52
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
if key.nil?
|
54
|
+
hash[key_without_index][index] = value
|
55
|
+
else
|
56
|
+
hash[key_without_index][index] ||= {}
|
57
|
+
hash[key_without_index][index][key] = value
|
58
|
+
end
|
55
59
|
end
|
56
|
-
end
|
57
60
|
|
58
|
-
|
59
|
-
|
61
|
+
def set_deep_hash_positioned_value(new_hash, base_key, value, child_key)
|
62
|
+
index = array_index(base_key)
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
if index
|
65
|
+
set_deep_hash_array_value(new_hash, base_key, index, value, child_key)
|
66
|
+
else
|
67
|
+
set_deep_hash_value(new_hash, base_key, value, child_key)
|
68
|
+
end
|
65
69
|
end
|
66
|
-
end
|
67
70
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
match[1].to_i
|
71
|
+
def array_index(key)
|
72
|
+
match = key.match(/\[([^)]+)\]/)
|
73
|
+
match && match[1].to_i
|
72
74
|
end
|
73
|
-
end
|
74
75
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
def set_deep_hash_value(hash, base_key, value, key = nil)
|
77
|
+
if key.nil?
|
78
|
+
hash[base_key] = value
|
79
|
+
else
|
80
|
+
hash[base_key] ||= {}
|
81
|
+
hash[base_key][key] = value
|
82
|
+
end
|
81
83
|
end
|
82
84
|
end
|
83
85
|
end
|
@@ -1,76 +1,86 @@
|
|
1
|
-
|
2
|
-
attr_reader :hash, :block
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
class Hash
|
4
|
+
class KeyChanger
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def remap(keys_map)
|
10
|
+
new_hash = {}
|
11
|
+
keys_map.each do |o, n|
|
12
|
+
new_hash[n] = hash.delete(o)
|
13
|
+
end
|
14
|
+
hash.merge! new_hash
|
15
|
+
end
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
def change_keys(settings = {}, &block)
|
18
|
+
merge_options({
|
19
|
+
recursive: true
|
20
|
+
}, settings)
|
21
|
+
|
22
|
+
if options[:recursive]
|
23
|
+
hash.deep_transform_keys!(&block)
|
24
|
+
else
|
25
|
+
hash.transform_keys!(&block)
|
26
|
+
end
|
17
27
|
end
|
18
|
-
end
|
19
28
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
29
|
+
def camelize_keys(settings = {})
|
30
|
+
merge_options({
|
31
|
+
uppercase_first_letter: true
|
32
|
+
}, settings)
|
24
33
|
|
25
|
-
|
34
|
+
type = options[:uppercase_first_letter] ? :upper : :lower
|
26
35
|
|
27
|
-
|
28
|
-
|
36
|
+
change_keys do |k|
|
37
|
+
k.camelize(type)
|
38
|
+
end
|
29
39
|
end
|
30
|
-
end
|
31
40
|
|
32
|
-
|
33
|
-
|
41
|
+
def underscore_keys(settings = {})
|
42
|
+
merge_options({}, settings)
|
34
43
|
|
35
|
-
|
36
|
-
k.underscore
|
44
|
+
change_keys(&:underscore)
|
37
45
|
end
|
38
|
-
end
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
47
|
+
def change_text(options = {})
|
48
|
+
merge_options({
|
49
|
+
type: :keep
|
50
|
+
}, options)
|
44
51
|
|
45
|
-
|
46
|
-
|
52
|
+
change_keys do |key|
|
53
|
+
cast_new_key yield(key), key.class
|
54
|
+
end
|
47
55
|
end
|
48
|
-
end
|
49
56
|
|
50
|
-
|
57
|
+
private
|
51
58
|
|
52
|
-
|
53
|
-
@options = {}.merge!(default).merge!(custom).merge!(options)
|
54
|
-
end
|
59
|
+
attr_reader :hash
|
55
60
|
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
def merge_options(default, custom)
|
62
|
+
@options = {}.merge!(default).merge!(custom).merge!(options)
|
63
|
+
end
|
59
64
|
|
60
|
-
|
61
|
-
|
62
|
-
when :symbol then
|
63
|
-
key.to_sym
|
64
|
-
when :string then
|
65
|
-
key.to_s
|
65
|
+
def options
|
66
|
+
@options ||= {}
|
66
67
|
end
|
67
|
-
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
def cast_new_key(key, old_clazz)
|
70
|
+
case class_cast(old_clazz)
|
71
|
+
when :symbol then
|
72
|
+
key.to_sym
|
73
|
+
when :string then
|
74
|
+
key.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def keep_class?
|
79
|
+
options[:type] == :keep
|
80
|
+
end
|
72
81
|
|
73
|
-
|
74
|
-
|
82
|
+
def class_cast(old_clazz)
|
83
|
+
keep_class? && old_clazz.to_s.downcase.to_sym || options[:type]
|
84
|
+
end
|
75
85
|
end
|
76
|
-
end
|
86
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
class KeysSorter
|
5
|
+
def initialize(hash, recursive: true)
|
6
|
+
@hash = hash
|
7
|
+
@recursive = recursive
|
8
|
+
end
|
9
|
+
|
10
|
+
def sort
|
11
|
+
{}.tap do |new_hash|
|
12
|
+
sorted_keys.each do |key|
|
13
|
+
new_hash[key] = change_value(hash[key])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def sorted_keys
|
21
|
+
hash.keys.sort
|
22
|
+
end
|
23
|
+
|
24
|
+
def change_value(value)
|
25
|
+
return value unless value.is_a?(Hash) && recursive
|
26
|
+
value.sort_keys(recursive: true)
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :hash, :recursive
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
module Squasher
|
5
|
+
class Builder
|
6
|
+
attr_reader :key, :value
|
7
|
+
|
8
|
+
def initialize(key, value)
|
9
|
+
@value = value
|
10
|
+
@key = key
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
if value.is_a? Hash
|
15
|
+
value.squash.inject({}) do |hash, (k, v)|
|
16
|
+
new_key = [key, k].join('.')
|
17
|
+
hash.merge!(new_key => v)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
{ key => value }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.squash(origin)
|
26
|
+
origin.inject({}) do |hash, (key, value)|
|
27
|
+
hash.merge!(Builder.new(key, value).to_h)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
class ToHashMapper
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
end
|
8
|
+
|
9
|
+
def map
|
10
|
+
{}.tap do |new_hash|
|
11
|
+
hash.each do |k, v|
|
12
|
+
new_hash[k] = yield(k, v)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :hash
|
20
|
+
end
|
21
|
+
end
|