nrser 0.0.30 → 0.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/nrser.rb +56 -12
- data/lib/nrser/collection.rb +4 -7
- data/lib/nrser/ext.rb +5 -0
- data/lib/nrser/{refinements → ext}/enumerable.rb +11 -9
- data/lib/nrser/ext/pathname.rb +74 -0
- data/lib/nrser/{refinements → ext}/tree.rb +2 -26
- data/lib/nrser/functions.rb +18 -0
- data/lib/nrser/{array.rb → functions/array.rb} +2 -3
- data/lib/nrser/{binding.rb → functions/binding.rb} +0 -2
- data/lib/nrser/functions/enumerable.rb +355 -0
- data/lib/nrser/functions/enumerable/find_all_map.rb +33 -0
- data/lib/nrser/functions/enumerable/find_map.rb +53 -0
- data/lib/nrser/functions/exception.rb +17 -0
- data/lib/nrser/{hash.rb → functions/hash.rb} +0 -0
- data/lib/nrser/functions/hash/bury.rb +147 -0
- data/lib/nrser/{hash → functions/hash}/deep_merge.rb +5 -5
- data/lib/nrser/{hash → functions/hash}/except_keys.rb +2 -0
- data/lib/nrser/{hash → functions/hash}/guess_label_key_type.rb +3 -1
- data/lib/nrser/{hash → functions/hash}/slice_keys.rb +3 -1
- data/lib/nrser/{hash → functions/hash}/stringify_keys.rb +2 -0
- data/lib/nrser/{hash → functions/hash}/symbolize_keys.rb +3 -1
- data/lib/nrser/{hash → functions/hash}/transform_keys.rb +3 -1
- data/lib/nrser/functions/merge_by.rb +29 -0
- data/lib/nrser/{object.rb → functions/object.rb} +0 -0
- data/lib/nrser/{object → functions/object}/as_array.rb +2 -0
- data/lib/nrser/{object → functions/object}/as_hash.rb +7 -5
- data/lib/nrser/{object → functions/object}/truthy.rb +46 -7
- data/lib/nrser/{open_struct.rb → functions/open_struct.rb} +0 -0
- data/lib/nrser/functions/path.rb +150 -0
- data/lib/nrser/{proc.rb → functions/proc.rb} +1 -22
- data/lib/nrser/functions/string.rb +297 -0
- data/lib/nrser/functions/string/looks_like.rb +44 -0
- data/lib/nrser/{text.rb → functions/text.rb} +0 -0
- data/lib/nrser/{text → functions/text}/indentation.rb +2 -16
- data/lib/nrser/{text → functions/text}/lines.rb +1 -2
- data/lib/nrser/{text → functions/text}/word_wrap.rb +2 -4
- data/lib/nrser/{tree.rb → functions/tree.rb} +0 -0
- data/lib/nrser/{tree → functions/tree}/each_branch.rb +6 -7
- data/lib/nrser/functions/tree/leaves.rb +92 -0
- data/lib/nrser/{tree → functions/tree}/map_branches.rb +31 -32
- data/lib/nrser/functions/tree/map_leaves.rb +56 -0
- data/lib/nrser/{tree → functions/tree}/map_tree.rb +9 -20
- data/lib/nrser/{tree → functions/tree}/transform.rb +0 -10
- data/lib/nrser/logger.rb +9 -10
- data/lib/nrser/message.rb +3 -7
- data/lib/nrser/meta.rb +2 -0
- data/lib/nrser/meta/class_attrs.rb +3 -9
- data/lib/nrser/meta/props.rb +19 -19
- data/lib/nrser/meta/props/base.rb +4 -10
- data/lib/nrser/meta/props/prop.rb +12 -28
- data/lib/nrser/no_arg.rb +1 -3
- data/lib/nrser/refinements.rb +5 -0
- data/lib/nrser/refinements/array.rb +5 -17
- data/lib/nrser/refinements/enumerator.rb +1 -3
- data/lib/nrser/refinements/hash.rb +3 -15
- data/lib/nrser/refinements/object.rb +2 -2
- data/lib/nrser/refinements/open_struct.rb +0 -2
- data/lib/nrser/refinements/pathname.rb +3 -46
- data/lib/nrser/refinements/set.rb +2 -6
- data/lib/nrser/refinements/string.rb +2 -2
- data/lib/nrser/rspex.rb +16 -13
- data/lib/nrser/types.rb +6 -20
- data/lib/nrser/types/any.rb +0 -1
- data/lib/nrser/types/booleans.rb +1 -1
- data/lib/nrser/types/combinators.rb +5 -5
- data/lib/nrser/types/in.rb +0 -21
- data/lib/nrser/types/responds.rb +1 -0
- data/lib/nrser/types/trees.rb +1 -0
- data/lib/nrser/version.rb +2 -3
- data/spec/nrser/{template_spec.rb → functions/binding/template_spec.rb} +0 -0
- data/spec/nrser/functions/enumerable/find_all_map_spec.rb +28 -0
- data/spec/nrser/functions/enumerable/find_bounded_spec.rb +70 -0
- data/spec/nrser/functions/enumerable/find_map_spec.rb +38 -0
- data/spec/nrser/functions/enumerable/find_only_spec.rb +25 -0
- data/spec/nrser/functions/enumerable/to_h_by_spec.rb +28 -0
- data/spec/nrser/{format_exception_spec.rb → functions/exception/format_exception_spec.rb} +0 -0
- data/spec/nrser/{hash → functions/hash}/bury_spec.rb +0 -0
- data/spec/nrser/{hash → functions/hash}/guess_label_key_type_spec.rb +0 -0
- data/spec/nrser/{hash_spec.rb → functions/hash_spec.rb} +0 -7
- data/spec/nrser/{merge_by_spec.rb → functions/merge_by_spec.rb} +0 -0
- data/spec/nrser/{truthy_spec.rb → functions/object/truthy_spec.rb} +0 -0
- data/spec/nrser/{open_struct_spec.rb → functions/open_struct_spec.rb} +0 -0
- data/spec/nrser/{string → functions/string}/common_prefix_spec.rb +0 -0
- data/spec/nrser/{string → functions/string}/looks_like_spec.rb +0 -0
- data/spec/nrser/{truncate_spec.rb → functions/string/truncate_spec.rb} +0 -0
- data/spec/nrser/{text → functions/text}/dedent/gotchas_spec.rb +0 -0
- data/spec/nrser/{text → functions/text}/dedent_spec.rb +0 -0
- data/spec/nrser/{indent_spec.rb → functions/text/indent_spec.rb} +0 -0
- data/spec/nrser/{tree → functions/tree}/each_branch_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/leaves_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/map_branch_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/map_tree_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/transform_spec.rb +0 -0
- data/spec/nrser/{tree → functions/tree}/transformer_spec.rb +0 -0
- data/spec/nrser/meta/class_attrs_spec.rb +12 -14
- data/spec/spec_helper.rb +2 -3
- metadata +136 -110
- data/lib/nrser/enumerable.rb +0 -288
- data/lib/nrser/exception.rb +0 -7
- data/lib/nrser/hash/bury.rb +0 -154
- data/lib/nrser/merge_by.rb +0 -26
- data/lib/nrser/string.rb +0 -294
- data/lib/nrser/string/looks_like.rb +0 -51
- data/lib/nrser/tree/leaves.rb +0 -92
- data/lib/nrser/tree/map_leaves.rb +0 -63
- data/spec/nrser/enumerable_spec.rb +0 -111
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module NRSER
|
|
2
|
+
|
|
3
|
+
# @!group Enumerable Functions
|
|
4
|
+
|
|
5
|
+
# Find all truthy (not `nil` or `false`) results of calling `&block`
|
|
6
|
+
# with entries from `enum`.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
#
|
|
10
|
+
# NRSER.find_all_map( [1, 2, 3, 4] ) do |i|
|
|
11
|
+
# if i.even?
|
|
12
|
+
# "#{ i } is even!"
|
|
13
|
+
# end
|
|
14
|
+
# end
|
|
15
|
+
# # => ["2 is even!", "4 is even!"]
|
|
16
|
+
#
|
|
17
|
+
# @param [Enumerable<E>] enum
|
|
18
|
+
# Entries to search (in order).
|
|
19
|
+
#
|
|
20
|
+
# @param [Proc<(E)=>R>] &block
|
|
21
|
+
# Block mapping entires to results.
|
|
22
|
+
#
|
|
23
|
+
# @return [nil]
|
|
24
|
+
# When `block.call( E )` is `nil` or `false` for all `E` in `enum`.
|
|
25
|
+
#
|
|
26
|
+
# @return [R]
|
|
27
|
+
# The first result `R = block.call( E )` where `R` is not `nil` or `false`.
|
|
28
|
+
#
|
|
29
|
+
def self.find_all_map enum, &block
|
|
30
|
+
enum.map( &block ).select { |entry| entry }
|
|
31
|
+
end # .find_map
|
|
32
|
+
|
|
33
|
+
end # module NRSER
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module NRSER
|
|
2
|
+
|
|
3
|
+
# @!group Enumerable Functions
|
|
4
|
+
|
|
5
|
+
# Find the first truthy (not `nil` or `false`) result of calling `&block`
|
|
6
|
+
# with entries from `enum`.
|
|
7
|
+
#
|
|
8
|
+
# Like {Enumerable#find}, accept an optional `ifnone` procedure to call if
|
|
9
|
+
# no match is found.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
#
|
|
13
|
+
# NRSER.find_map( [1, 2, 3, 4] ) do |i|
|
|
14
|
+
# if i.even?
|
|
15
|
+
# "#{ i } is even!"
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
# # => "2 is even!"
|
|
19
|
+
#
|
|
20
|
+
# @param [Enumerable<E>] enum
|
|
21
|
+
# Entries to search (in order).
|
|
22
|
+
#
|
|
23
|
+
# @param [nil | Proc<()=>DEFAULT>] ifnone
|
|
24
|
+
# Optional lambda to call for the return value when no match is found.
|
|
25
|
+
#
|
|
26
|
+
# @param [Proc<(E)=>RESLUT>] &block
|
|
27
|
+
# Block mapping entires to results.
|
|
28
|
+
#
|
|
29
|
+
# @return [nil]
|
|
30
|
+
# When `block.call( E )` is `nil` or `false` for all `E` in `enum`
|
|
31
|
+
# *and* `ifnone` is `nil` or not provided.
|
|
32
|
+
#
|
|
33
|
+
# @return [V]
|
|
34
|
+
# When `block.call( E )` is `nil` or `false` for all `E` in `enum`
|
|
35
|
+
# *and* `ifnone` is a lambda that returns `DEFAULT`.
|
|
36
|
+
#
|
|
37
|
+
# @return [R]
|
|
38
|
+
# The first result `RESLUT = block.call( E )`
|
|
39
|
+
# where `RESLUT` is not `nil` or `false`.
|
|
40
|
+
#
|
|
41
|
+
def self.find_map enum, ifnone = nil, &block
|
|
42
|
+
enum.each do |entry|
|
|
43
|
+
if result = block.call( entry )
|
|
44
|
+
# Found a match, short-circuit
|
|
45
|
+
return result
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# No matches, return `ifnone`
|
|
50
|
+
ifnone.call if ifnone
|
|
51
|
+
end # .find_map
|
|
52
|
+
|
|
53
|
+
end # module NRSER
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module NRSER
|
|
2
|
+
# @!group Exception Functions
|
|
3
|
+
|
|
4
|
+
# String format an exception the same way they are printed to the CLI when
|
|
5
|
+
# not handled (when they crash programs - what you're used to seeing),
|
|
6
|
+
# including the message, class and backtrace.
|
|
7
|
+
#
|
|
8
|
+
# @param [Exception] e
|
|
9
|
+
# Exception to format.
|
|
10
|
+
#
|
|
11
|
+
# @return [String]
|
|
12
|
+
#
|
|
13
|
+
def self.format_exception e
|
|
14
|
+
"#{ e.message } (#{ e.class }):\n #{ e.backtrace.join("\n ") }"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end # module NRSER
|
|
File without changes
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Definitions
|
|
2
|
+
# =======================================================================
|
|
3
|
+
|
|
4
|
+
module NRSER
|
|
5
|
+
|
|
6
|
+
# @!group Hash Functions
|
|
7
|
+
|
|
8
|
+
# The opposite of `#dig` - set a value at a deep key path, creating
|
|
9
|
+
# necessary structures along the way and optionally clobbering whatever's
|
|
10
|
+
# in the way to achieve success.
|
|
11
|
+
#
|
|
12
|
+
# @param [Hash] hash
|
|
13
|
+
# Hash to bury the value in.
|
|
14
|
+
#
|
|
15
|
+
# @param [Array | #to_s] key_path
|
|
16
|
+
# - When an {Array}, each entry is used exactly as-is for each key.
|
|
17
|
+
#
|
|
18
|
+
# - Otherwise, the `key_path` is converted to a string and split by
|
|
19
|
+
# `.` to produce the key array, and the actual keys used depend on
|
|
20
|
+
# the `parsed_key_type` option.
|
|
21
|
+
#
|
|
22
|
+
# @param [Object] value
|
|
23
|
+
# The value to set at the end of the path.
|
|
24
|
+
#
|
|
25
|
+
# @param [Class | :guess] parsed_key_type:
|
|
26
|
+
# How to handle parsed key path segments:
|
|
27
|
+
#
|
|
28
|
+
# - `String` - use the strings that naturally split from a parsed
|
|
29
|
+
# key path.
|
|
30
|
+
#
|
|
31
|
+
# Note that this is the *String class itself, **not** a value that
|
|
32
|
+
# is a String*.
|
|
33
|
+
#
|
|
34
|
+
# - `Symbol` - convert the strings that are split from the key path
|
|
35
|
+
# to symbols.
|
|
36
|
+
#
|
|
37
|
+
# Note that this is the *Symbol class itself, **not** a value that
|
|
38
|
+
# is a Symbol*.``
|
|
39
|
+
#
|
|
40
|
+
# - `:guess` (default) -
|
|
41
|
+
#
|
|
42
|
+
# @return [return_type]
|
|
43
|
+
# @todo Document return value.
|
|
44
|
+
#
|
|
45
|
+
def self.bury! hash,
|
|
46
|
+
key_path,
|
|
47
|
+
value,
|
|
48
|
+
parsed_key_type: :guess,
|
|
49
|
+
clobber: false,
|
|
50
|
+
create_arrays_for_unsigned_keys: false
|
|
51
|
+
|
|
52
|
+
# Parse the key if it's not an array
|
|
53
|
+
unless key_path.is_a?( Array )
|
|
54
|
+
key_path = key_path.to_s.split '.'
|
|
55
|
+
|
|
56
|
+
# Convert the keys to symbols now if that's what we want to use
|
|
57
|
+
if parsed_key_type == Symbol
|
|
58
|
+
key_path.map! &:to_sym
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
_internal_bury! \
|
|
63
|
+
hash,
|
|
64
|
+
key_path,
|
|
65
|
+
value,
|
|
66
|
+
guess_key_type: ( parsed_key_type == :guess ),
|
|
67
|
+
clobber: clobber,
|
|
68
|
+
create_arrays_for_unsigned_keys: create_arrays_for_unsigned_keys
|
|
69
|
+
end # .bury!
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# @todo Document _internal_bury! method.
|
|
73
|
+
#
|
|
74
|
+
# @private
|
|
75
|
+
#
|
|
76
|
+
# @param [type] arg_name
|
|
77
|
+
# @todo Add name param description.
|
|
78
|
+
#
|
|
79
|
+
# @return [return_type]
|
|
80
|
+
# @todo Document return value.
|
|
81
|
+
#
|
|
82
|
+
def self._internal_bury! tree,
|
|
83
|
+
key_path,
|
|
84
|
+
value,
|
|
85
|
+
guess_key_type:,
|
|
86
|
+
clobber:,
|
|
87
|
+
create_arrays_for_unsigned_keys:
|
|
88
|
+
|
|
89
|
+
# Split the key path into the current key and the rest of the keys
|
|
90
|
+
key, *rest = key_path
|
|
91
|
+
|
|
92
|
+
# If we are
|
|
93
|
+
#
|
|
94
|
+
# - Guessing the key type
|
|
95
|
+
# - The tree is keyed
|
|
96
|
+
# - The tree uses some {Symbol} (and no {String}) keys
|
|
97
|
+
#
|
|
98
|
+
# then convert the key to a symbol.
|
|
99
|
+
#
|
|
100
|
+
if guess_key_type &&
|
|
101
|
+
tree.respond_to?( :keys ) &&
|
|
102
|
+
guess_label_key_type( tree ) == Symbol
|
|
103
|
+
key = key.to_sym
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Terminating case: we're at the last segment
|
|
107
|
+
if rest.empty?
|
|
108
|
+
# Set the value
|
|
109
|
+
tree[key] = value
|
|
110
|
+
|
|
111
|
+
else
|
|
112
|
+
# Go deeper...
|
|
113
|
+
|
|
114
|
+
# See if there is a hash in place
|
|
115
|
+
unless NRSER::Types.tree.test tree[key]
|
|
116
|
+
# There is not... so we need to do some figurin'
|
|
117
|
+
|
|
118
|
+
# If we're clobbering or the hash has no value, we're good:
|
|
119
|
+
# assign a new hash to set in
|
|
120
|
+
if clobber || tree[key].nil?
|
|
121
|
+
if create_arrays_for_unsigned_keys &&
|
|
122
|
+
NRSER::Types.unsigned.test( key )
|
|
123
|
+
tree[key] = []
|
|
124
|
+
else
|
|
125
|
+
tree[key] = {}
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
else
|
|
129
|
+
# We've got an intractable state conflict; raise
|
|
130
|
+
raise NRSER::ConflictError.new squish <<-END
|
|
131
|
+
can not set key #{ key.inspect } due to conflicting value
|
|
132
|
+
#{ tree[key].inspect } in tree #{ tree.inspect } (:clobber
|
|
133
|
+
option not set)
|
|
134
|
+
END
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
end # unless hash[key].is_a?( Hash )
|
|
138
|
+
|
|
139
|
+
# Dive in...
|
|
140
|
+
bury! tree[key], rest, value
|
|
141
|
+
|
|
142
|
+
end # if rest.empty? / else
|
|
143
|
+
end # ._internal_bury!
|
|
144
|
+
|
|
145
|
+
private_class_method :_internal_bury!
|
|
146
|
+
|
|
147
|
+
end # module NRSER
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
1
|
# Definitions
|
|
3
2
|
# =======================================================================
|
|
4
3
|
|
|
5
4
|
module NRSER
|
|
6
5
|
|
|
6
|
+
# @!group Hash Functions
|
|
7
|
+
|
|
7
8
|
# Returns a new hash created by recursively merging `other_hash` on top of
|
|
8
9
|
# `base_hash`.
|
|
9
10
|
#
|
|
@@ -12,7 +13,7 @@ module NRSER
|
|
|
12
13
|
# @see https://github.com/rails/rails/blob/23c8f6918d4e6b9a823aa7a91377c6e3b5d60e13/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
|
|
13
14
|
#
|
|
14
15
|
# @param [Hash] base_hash
|
|
15
|
-
# Base hash - it's values will be overwritten by any key paths shared with
|
|
16
|
+
# Base hash - it's values will be overwritten by any key paths shared with
|
|
16
17
|
# the other hash.
|
|
17
18
|
#
|
|
18
19
|
# @param [Hash] other_hash
|
|
@@ -38,7 +39,7 @@ module NRSER
|
|
|
38
39
|
other_hash.each_pair do |current_key, other_value|
|
|
39
40
|
this_value = base_hash[current_key]
|
|
40
41
|
|
|
41
|
-
base_hash[current_key] = if this_value.is_a?(Hash) &&
|
|
42
|
+
base_hash[current_key] = if this_value.is_a?(Hash) &&
|
|
42
43
|
other_value.is_a?(Hash)
|
|
43
44
|
deep_merge this_value, other_value, &block
|
|
44
45
|
else
|
|
@@ -52,6 +53,5 @@ module NRSER
|
|
|
52
53
|
|
|
53
54
|
base_hash
|
|
54
55
|
end
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
end # module NRSER
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
# =======================================================================
|
|
3
3
|
|
|
4
4
|
module NRSER
|
|
5
|
+
|
|
6
|
+
# @!group Hash Functions
|
|
5
7
|
|
|
6
|
-
# Guess which type of "label" key - strings or symbols - a hash (or other
|
|
8
|
+
# Guess which type of "label" key - strings or symbols - a hash (or other
|
|
7
9
|
# object that responds to `#keys` and `#empty`) uses.
|
|
8
10
|
#
|
|
9
11
|
# @param [#keys & #empty] keyed
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
# =======================================================================
|
|
3
3
|
|
|
4
4
|
module NRSER
|
|
5
|
+
|
|
6
|
+
# @!group Hash Functions
|
|
5
7
|
|
|
6
8
|
# Lifted from ActiveSupport.
|
|
7
9
|
#
|
|
@@ -21,7 +23,7 @@ module NRSER
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
# Meant to be a drop-in replacement for the ActiveSupport version, though
|
|
24
|
-
# I've changed the implementation a bit... because honestly I didn't
|
|
26
|
+
# I've changed the implementation a bit... because honestly I didn't
|
|
25
27
|
# understand why they were doing it the way they do :/
|
|
26
28
|
#
|
|
27
29
|
# @see http://www.rubydoc.info/gems/activesupport/5.1.3/Hash:slice!
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
module NRSER
|
|
5
5
|
|
|
6
|
+
# @!group Hash Functions
|
|
7
|
+
|
|
6
8
|
# Mutates `hash` by converting all keys that respond to `#to_sym` to symbols.
|
|
7
9
|
#
|
|
8
10
|
# Lifted from ActiveSupport.
|
|
@@ -36,7 +38,7 @@ module NRSER
|
|
|
36
38
|
transform_keys(hash) { |key| key.to_sym rescue key }
|
|
37
39
|
end
|
|
38
40
|
|
|
39
|
-
singleton_class.send :alias_method, :to_sym_keys, :symbolize_keys
|
|
41
|
+
singleton_class.send :alias_method, :to_sym_keys, :symbolize_keys
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
# @todo Document deep_symbolize_keys method.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module NRSER
|
|
2
2
|
|
|
3
|
+
# @!group Hash Functions
|
|
4
|
+
|
|
3
5
|
# Lifted from ActiveSupport.
|
|
4
6
|
#
|
|
5
7
|
# @see http://www.rubydoc.info/gems/activesupport/5.1.3/Hash:transform_keys!
|
|
@@ -84,7 +86,7 @@ module NRSER
|
|
|
84
86
|
# Anything; see examples.
|
|
85
87
|
#
|
|
86
88
|
# @param [Proc] &block
|
|
87
|
-
# Proc that should accept each key as it's only argument and return the
|
|
89
|
+
# Proc that should accept each key as it's only argument and return the
|
|
88
90
|
# new key to replace it with.
|
|
89
91
|
#
|
|
90
92
|
def self.deep_transform_keys object, &block
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module NRSER
|
|
2
|
+
|
|
3
|
+
# Deep merge arrays of data hashes, matching hashes by computing a key with
|
|
4
|
+
# `&merge_key`.
|
|
5
|
+
#
|
|
6
|
+
# Uses {NRSER.deep_merge!} to merge.
|
|
7
|
+
#
|
|
8
|
+
# @param [Array<Hash>] current
|
|
9
|
+
# Current (base) array of hashes to start with (lowest predominance).
|
|
10
|
+
#
|
|
11
|
+
# @param [Array<Hash>] *updates
|
|
12
|
+
# One or more arrays of update hashes to merge over `current` (last is
|
|
13
|
+
# highest predominance).
|
|
14
|
+
#
|
|
15
|
+
# @param [Proc<(Hash)=>Object>] &merge_key
|
|
16
|
+
# Each hash is passed to `&merge_key` and the result is used to match
|
|
17
|
+
# hashes for merge. Must not return equal values for two different hashes
|
|
18
|
+
# in any of the arrays (`current` or any of `*updates`).
|
|
19
|
+
#
|
|
20
|
+
# @return [Array<Hash>]
|
|
21
|
+
# Final array of merged hashes. Don't depend on order.
|
|
22
|
+
#
|
|
23
|
+
def self.merge_by current, *updates, &merge_key
|
|
24
|
+
updates.reduce( to_h_by current, &merge_key ) { |result, update|
|
|
25
|
+
deep_merge! result, to_h_by( update, &merge_key )
|
|
26
|
+
}.values
|
|
27
|
+
end # .merge_by
|
|
28
|
+
|
|
29
|
+
end # module NRSER
|
|
File without changes
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module NRSER
|
|
2
2
|
|
|
3
|
+
# @!group Object Functions
|
|
4
|
+
|
|
3
5
|
# Treat the value as the value for `key` in a hash if it's not already a
|
|
4
6
|
# hash and can't be converted to one:
|
|
5
7
|
#
|
|
@@ -13,7 +15,7 @@ module NRSER
|
|
|
13
15
|
# 4. Otherwise, return a new hash where `key` points to the value.
|
|
14
16
|
# **`key` MUST be provided in this case.**
|
|
15
17
|
#
|
|
16
|
-
# Useful in method overloading and similar situations where you expect a
|
|
18
|
+
# Useful in method overloading and similar situations where you expect a
|
|
17
19
|
# hash that may specify a host of options, but want to allow the method
|
|
18
20
|
# to be called with a single value that corresponds to a default key in that
|
|
19
21
|
# option hash.
|
|
@@ -54,9 +56,9 @@ module NRSER
|
|
|
54
56
|
# ---------------------
|
|
55
57
|
#
|
|
56
58
|
# Right now, {.as_hash} also tests if `value` responds to `#to_h`, and will
|
|
57
|
-
# try to call it, using the result if it doesn't raise. This lets it deal
|
|
59
|
+
# try to call it, using the result if it doesn't raise. This lets it deal
|
|
58
60
|
# with Ruby's "I used to be a Hash until someone mapped me" values like
|
|
59
|
-
# `[[:class, 'address']]`. I'm not sure if this is the best approach, but
|
|
61
|
+
# `[[:class, 'address']]`. I'm not sure if this is the best approach, but
|
|
60
62
|
# I'm going to try it for now and see how it pans out in actual usage.
|
|
61
63
|
#
|
|
62
64
|
# @todo
|
|
@@ -67,7 +69,7 @@ module NRSER
|
|
|
67
69
|
# The value that we want to be a hash.
|
|
68
70
|
#
|
|
69
71
|
# @param [Object] key [default nil]
|
|
70
|
-
# The key that `value` will be stored under in the result if `value` is
|
|
72
|
+
# The key that `value` will be stored under in the result if `value` is
|
|
71
73
|
# not a hash or can't be turned into one via `#to_h`. If this happens
|
|
72
74
|
# this value can **NOT** be `nil` or an `ArgumentError` is raised.
|
|
73
75
|
#
|
|
@@ -75,7 +77,7 @@ module NRSER
|
|
|
75
77
|
#
|
|
76
78
|
# @raise [ArgumentError]
|
|
77
79
|
# If it comes to constructing a new Hash with `value` as a value and no
|
|
78
|
-
# argument was provided
|
|
80
|
+
# argument was provided
|
|
79
81
|
#
|
|
80
82
|
def self.as_hash value, key = nil
|
|
81
83
|
return value if value.is_a? Hash
|