nrser 0.0.20 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -6
- data/lib/nrser/collection.rb +58 -20
- data/lib/nrser/enumerable.rb +155 -25
- data/lib/nrser/errors.rb +9 -0
- data/lib/nrser/hash.rb +1 -17
- data/lib/nrser/meta/class_attrs.rb +59 -9
- data/lib/nrser/open_struct.rb +60 -0
- data/lib/nrser/refinements/array.rb +4 -5
- data/lib/nrser/refinements/enumerable.rb +41 -0
- data/lib/nrser/refinements/enumerator.rb +7 -0
- data/lib/nrser/refinements/exception.rb +28 -0
- data/lib/nrser/refinements/hash.rb +9 -7
- data/lib/nrser/refinements/open_struct.rb +30 -0
- data/lib/nrser/refinements/set.rb +9 -0
- data/lib/nrser/refinements/string.rb +9 -0
- data/lib/nrser/refinements.rb +3 -0
- data/lib/nrser/types/attrs.rb +62 -35
- data/lib/nrser/types/bounded.rb +21 -4
- data/lib/nrser/types/combinators.rb +8 -4
- data/lib/nrser/types/is.rb +1 -1
- data/lib/nrser/types/responds.rb +110 -0
- data/lib/nrser/types/strings.rb +6 -0
- data/lib/nrser/types/type.rb +11 -6
- data/lib/nrser/types.rb +41 -6
- data/lib/nrser/version.rb +50 -1
- data/lib/nrser.rb +1 -0
- data/spec/nrser/enumerable_spec.rb +97 -0
- data/spec/nrser/hash_spec.rb +46 -2
- data/spec/nrser/open_struct_spec.rb +94 -0
- data/spec/nrser/refinements/array_spec.rb +25 -1
- data/spec/nrser/refinements/hash_spec.rb +30 -0
- data/spec/nrser/refinements/set_spec.rb +41 -0
- data/spec/nrser/types_spec.rb +13 -3
- metadata +58 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e94f9b40217a5d9e632cf2baa64d5e5e0d39cf23
|
4
|
+
data.tar.gz: 5bd0fc14f35efd8c8c42873eddf35ec3261aa483
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77102788f88d0de577d33e617b6b3fadf98c64c8fccec2415440d708f071518133147e9bea3bd6eedd02ee038fd3b23f578985edd80e2706a8611d30bb92b626
|
7
|
+
data.tar.gz: 98163e885104844aae596aa379f970780d271df8fdbeeae76f25a31460635c2de5bc1f8eec7008e67038ea84e7c35a5047676d3ee7d80504e7c6d82e1894c048
|
data/README.md
CHANGED
@@ -26,10 +26,7 @@ Or install it yourself as:
|
|
26
26
|
|
27
27
|
$ gem install nrser
|
28
28
|
|
29
|
-
## Contributing
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
35
|
-
5. Create a new Pull Request
|
30
|
+
## Design
|
31
|
+
|
32
|
+
|
data/lib/nrser/collection.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'set'
|
2
|
+
require 'ostruct'
|
2
3
|
|
3
4
|
module NRSER
|
4
5
|
# include this module in any custom classes to have them treated as
|
@@ -10,9 +11,13 @@ module NRSER
|
|
10
11
|
Array,
|
11
12
|
Hash,
|
12
13
|
Set,
|
14
|
+
OpenStruct,
|
13
15
|
]
|
14
16
|
end
|
15
17
|
|
18
|
+
# Eigenclass (Singleton Class)
|
19
|
+
# ========================================================================
|
20
|
+
#
|
16
21
|
class << self
|
17
22
|
|
18
23
|
# test if an object is considered a collection.
|
@@ -24,40 +29,73 @@ module NRSER
|
|
24
29
|
Collection::STDLIB.any? {|cls| obj.is_a? cls} || obj.is_a?(Collection)
|
25
30
|
end
|
26
31
|
|
27
|
-
|
32
|
+
|
33
|
+
# Yield on each element of a collection or on the object itself if it's
|
28
34
|
# not a collection. avoids having to normalize to an array to iterate over
|
29
35
|
# something that may be an object OR a collection of objects.
|
30
36
|
#
|
31
|
-
#
|
37
|
+
# **NOTE** Implemented for our idea of a collection instead of testing
|
38
|
+
# for response to `#each` (or similar) to avoid catching things
|
39
|
+
# like {IO} instances, which include {Enumerable} but are
|
40
|
+
# probably not what is desired when using {NRSER.each}
|
41
|
+
# (more likely that you mean "I expect one or more files" than
|
42
|
+
# "I expect one or more strings which may be represented by
|
43
|
+
# lines in an open {File}").
|
44
|
+
#
|
45
|
+
# @param [Object] object
|
46
|
+
# Target object.
|
32
47
|
#
|
33
|
-
# @yield
|
48
|
+
# @yield
|
49
|
+
# Each element of a collection or the target object itself.
|
34
50
|
#
|
35
|
-
# @return [Object]
|
51
|
+
# @return [Object]
|
52
|
+
# `object` param.
|
36
53
|
#
|
37
|
-
def each
|
38
|
-
if collection?
|
39
|
-
|
54
|
+
def each object, &block
|
55
|
+
if collection? object
|
56
|
+
# We need to test for response because {OpenStruct} *will* respond to
|
57
|
+
# #each because *it will respond to anything* (which sucks), but it
|
58
|
+
# will return `false` for `respond_to? :each` and the like, and this
|
59
|
+
# behavior could be shared by other collection objects, so it seems
|
60
|
+
# like a decent idea.
|
61
|
+
if object.respond_to? :each_pair
|
62
|
+
object.each_pair &block
|
63
|
+
elsif object.respond_to? :each
|
64
|
+
object.each &block
|
65
|
+
else
|
66
|
+
raise TypeError.squished <<-END
|
67
|
+
Object #{ obj.inpsect } does not respond to #each or #each_pair
|
68
|
+
END
|
69
|
+
end
|
40
70
|
else
|
41
|
-
block.call
|
42
|
-
obj
|
71
|
+
block.call object
|
43
72
|
end
|
73
|
+
object
|
44
74
|
end
|
45
75
|
|
46
|
-
|
76
|
+
|
77
|
+
# If `object` is a collection, calls `#map` with the block. Otherwise,
|
47
78
|
# applies block to the object and returns the result.
|
48
79
|
#
|
49
|
-
#
|
80
|
+
# See note in {NRSER.each} for discussion of why this tests for a
|
81
|
+
# collection instead of duck-typing `#map`.
|
82
|
+
#
|
83
|
+
# @param [Object] object
|
84
|
+
# Target object.
|
50
85
|
#
|
51
|
-
# @yield
|
86
|
+
# @yield
|
87
|
+
# Each element of a collection or the target object itself.
|
52
88
|
#
|
53
|
-
# @return [Object]
|
89
|
+
# @return [Object]
|
90
|
+
# The result of mapping or applying the block.
|
54
91
|
#
|
55
|
-
def map
|
56
|
-
if collection?
|
57
|
-
|
92
|
+
def map object, &block
|
93
|
+
if collection? object
|
94
|
+
object.map &block
|
58
95
|
else
|
59
|
-
block.call
|
96
|
+
block.call object
|
60
97
|
end
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
98
|
+
end # #map
|
99
|
+
|
100
|
+
end # class << self
|
101
|
+
end # module NRSER
|
data/lib/nrser/enumerable.rb
CHANGED
@@ -1,31 +1,161 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
require_relative './errors'
|
4
|
+
|
1
5
|
module NRSER
|
2
|
-
|
3
|
-
#
|
6
|
+
|
7
|
+
# Eigenclass (Singleton Class)
|
8
|
+
# ========================================================================
|
4
9
|
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# and
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
10
|
+
class << self
|
11
|
+
# Maps an enumerable object to a *new* hash with the same keys and values
|
12
|
+
# obtained by calling `block` with the current key and value.
|
13
|
+
#
|
14
|
+
# If `enumerable` *does not* respond to `#to_pairs` then it's
|
15
|
+
# treated as a hash where the elements iterated by `#each` are it's keys
|
16
|
+
# and all it's values are `nil`.
|
17
|
+
#
|
18
|
+
# In this way, {NRSER.map_values} handles Hash, Array, Set, OpenStruct,
|
19
|
+
# and probably pretty much anything else reasonable you may throw at it.
|
20
|
+
#
|
21
|
+
# @param [#each_pair, #each] enumerable
|
22
|
+
#
|
23
|
+
# @yieldparam [Object] key
|
24
|
+
# The key that will be used for whatever value the block returns in the
|
25
|
+
# new hash.
|
26
|
+
#
|
27
|
+
# @yieldparam [nil, Object] value
|
28
|
+
# If `enumerable` responds to `#each_pair`, the second parameter it yielded
|
29
|
+
# along with `key`. Otherwise `nil`.
|
30
|
+
#
|
31
|
+
# @yieldreturn [Object]
|
32
|
+
# Value for the new hash.
|
33
|
+
#
|
34
|
+
# @return [Hash]
|
35
|
+
#
|
36
|
+
# @raise [TypeError]
|
37
|
+
# If `enumerable` does not respond to `#each_pair` or `#each`.
|
38
|
+
#
|
39
|
+
def map_values enumerable, &block
|
40
|
+
result = {}
|
41
|
+
|
42
|
+
if enumerable.respond_to? :each_pair
|
43
|
+
enumerable.each_pair { |key, value|
|
44
|
+
result[key] = block.call key, value
|
45
|
+
}
|
46
|
+
elsif enumerable.respond_to? :each
|
47
|
+
enumerable.each { |key|
|
48
|
+
result[key] = block.call key, nil
|
49
|
+
}
|
50
|
+
else
|
51
|
+
raise TypeError.new NRSER.squish <<-END
|
52
|
+
First argument must respond to #each_pair or #each
|
53
|
+
(found #{ enumerable.inspect })
|
54
|
+
END
|
55
|
+
end
|
56
|
+
|
57
|
+
result
|
58
|
+
end # #map_values
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
# @todo Document find_bounded method.
|
63
|
+
#
|
64
|
+
# @param [type] arg_name
|
65
|
+
# @todo Add name param description.
|
66
|
+
#
|
67
|
+
# @return [return_type]
|
68
|
+
# @todo Document return value.
|
69
|
+
#
|
70
|
+
def find_bounded enum, bounds, &block
|
71
|
+
NRSER::Types.
|
72
|
+
length(bounds).
|
73
|
+
check(enum.find_all &block) { |type:, value:|
|
74
|
+
NRSER.dedent <<-END
|
75
|
+
|
76
|
+
Length of found elements (#{ value.length }) FAILED to satisfy #{ type.to_s }
|
77
|
+
|
78
|
+
Found:
|
79
|
+
#{ NRSER.indent value.pretty_inspect }
|
80
|
+
|
81
|
+
Enumerable:
|
82
|
+
#{ NRSER.indent enum.pretty_inspect }
|
83
|
+
|
84
|
+
END
|
85
|
+
}
|
86
|
+
end # #find_bounded
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
# @todo Document find_only method.
|
91
|
+
#
|
92
|
+
# @param [type] arg_name
|
93
|
+
# @todo Add name param description.
|
94
|
+
#
|
95
|
+
# @return [return_type]
|
96
|
+
# @todo Document return value.
|
97
|
+
#
|
98
|
+
def find_only enum, &block
|
99
|
+
find_bounded(enum, 1, &block).first
|
100
|
+
end # #find_only
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
# @todo Document to_h_by method.
|
105
|
+
#
|
106
|
+
# @param [type] arg_name
|
107
|
+
# @todo Add name param description.
|
108
|
+
#
|
109
|
+
# @return [return_type]
|
110
|
+
# @todo Document return value.
|
111
|
+
#
|
112
|
+
def to_h_by enum, &block
|
113
|
+
{}.tap { |result|
|
114
|
+
enum.each { |element|
|
115
|
+
key = block.call element
|
116
|
+
|
117
|
+
if result.key? key
|
118
|
+
raise NRSER::ConflictError.dedented <<-END
|
119
|
+
Key #{ key.inspect } is already in results with value:
|
120
|
+
|
121
|
+
#{ result[key].pretty_inspect }
|
122
|
+
END
|
123
|
+
end
|
124
|
+
|
125
|
+
result[key] = element
|
126
|
+
}
|
127
|
+
}
|
128
|
+
end # #to_h_by
|
129
|
+
|
130
|
+
|
131
|
+
# Create an {Enumerator} that iterates over the "values" of an
|
132
|
+
# {Enumerable} `enum`. If `enum` responds to `#each_value` than we return
|
133
|
+
# that. Otherwise, we return `#each_entry`.
|
134
|
+
#
|
135
|
+
# @param [Enumerable] enum
|
136
|
+
#
|
137
|
+
# @return [Enumerator]
|
138
|
+
#
|
139
|
+
# @raise [TypeError]
|
140
|
+
# If `enum` doesn't respond to `#each_value` or `#each_entry`.
|
141
|
+
#
|
142
|
+
def enumerate_as_values enum
|
143
|
+
# NRSER.match enum,
|
144
|
+
# t.respond_to(:each_value), :each_value.to_proc,
|
145
|
+
# t.respond_to(:each_entry), :each_entry.to_proc
|
146
|
+
#
|
147
|
+
if enum.respond_to? :each_value
|
148
|
+
enum.each_value
|
149
|
+
elsif enum.respond_to? :each_entry
|
150
|
+
enum.each_entry
|
22
151
|
else
|
23
|
-
|
152
|
+
raise TypeError.squished <<-END
|
153
|
+
Expected `enum` arg to respond to :each_value or :each_entry,
|
154
|
+
found #{ enum.inspect }
|
155
|
+
END
|
24
156
|
end
|
25
|
-
end
|
157
|
+
end # #enumerate_as_values
|
158
|
+
|
26
159
|
|
27
|
-
|
28
|
-
enumerable.each { |key| result[key] = block.call key, nil }
|
29
|
-
result
|
30
|
-
end
|
160
|
+
end # class << self (Eigenclass)
|
31
161
|
end # module NRSER
|
data/lib/nrser/errors.rb
ADDED
data/lib/nrser/hash.rb
CHANGED
@@ -116,22 +116,6 @@ module NRSER
|
|
116
116
|
|
117
117
|
|
118
118
|
|
119
|
-
# @todo Document map_hash_values method.
|
120
|
-
#
|
121
|
-
# @param [Hash] hash
|
122
|
-
# @todo Add name param description.
|
123
|
-
#
|
124
|
-
# @return [return_type]
|
125
|
-
# @todo Document return value.
|
126
|
-
#
|
127
|
-
def self.map_hash_values hash, &block
|
128
|
-
result = {}
|
129
|
-
hash.each { |key, value| result[key] = block.call key, value }
|
130
|
-
result
|
131
|
-
end # #map_hash_values
|
132
|
-
|
133
|
-
|
134
|
-
|
135
119
|
# Lifted from ActiveSupport
|
136
120
|
# =====================================================================
|
137
121
|
#
|
@@ -228,7 +212,7 @@ module NRSER
|
|
228
212
|
end
|
229
213
|
|
230
214
|
# My-style name
|
231
|
-
singleton_class.send :alias_method, :
|
215
|
+
singleton_class.send :alias_method, :map_keys, :transform_keys
|
232
216
|
|
233
217
|
|
234
218
|
# Mutates `hash` by converting all keys that respond to `#to_sym` to symbols.
|
@@ -28,26 +28,66 @@ module ClassAttrs
|
|
28
28
|
# Class methods to extend the receiver with when {NRSER::Meta::ClassAttrs}
|
29
29
|
# is included.
|
30
30
|
module ClassMethods
|
31
|
-
def instance_variable_lookup
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
def instance_variable_lookup name,
|
32
|
+
default: NRSER::NO_ARG,
|
33
|
+
default_from: NRSER::NO_ARG
|
34
|
+
|
35
|
+
# If it's defined here on self, return that
|
36
|
+
if instance_variable_defined? name
|
37
|
+
return instance_variable_get name
|
38
|
+
end
|
39
|
+
|
40
|
+
# Ok, now to need to look for it.
|
41
|
+
|
42
|
+
# See if the superclass has the lookup method
|
43
|
+
if superclass.respond_to? :instance_variable_lookup
|
44
|
+
# It does. See what we get from that. We create a new object to use
|
45
|
+
# as a flag and assign it to `default` so we can tell if the search
|
46
|
+
# failed.
|
47
|
+
not_found = Object.new
|
48
|
+
result = superclass.instance_variable_lookup name, default: not_found
|
49
|
+
|
50
|
+
# If we found something, return it.
|
51
|
+
return result unless result == not_found
|
52
|
+
|
53
|
+
end # if superclass.respond_to? :instance_variable_lookup
|
54
|
+
|
55
|
+
# Ok, nothing was found.
|
56
|
+
|
57
|
+
# See if we can use a default...
|
58
|
+
if default != NRSER::NO_ARG || default_from != NRSER::NO_ARG
|
59
|
+
# We can use a default.
|
60
|
+
# `default` takes precedence.
|
61
|
+
if default != NRSER::NO_ARG
|
62
|
+
default
|
63
|
+
else
|
64
|
+
send default_from
|
65
|
+
end
|
66
|
+
|
36
67
|
else
|
68
|
+
# Nope, we can't, raise.
|
37
69
|
raise NoMethodError.new NRSER.squish <<-END
|
38
70
|
#{ name.inspect } is not defined anywhere in the class hierarchy
|
39
71
|
END
|
40
|
-
end
|
41
|
-
end
|
42
72
|
|
43
|
-
|
73
|
+
end # if we have a default value / else
|
74
|
+
|
75
|
+
end # #instance_variable_lookup
|
76
|
+
|
77
|
+
|
78
|
+
def class_attr_accessor attr,
|
79
|
+
default: NRSER::NO_ARG,
|
80
|
+
default_from: NRSER::NO_ARG
|
81
|
+
|
44
82
|
var_name = "@#{ attr }".to_sym
|
45
83
|
|
46
84
|
singleton_class.class_eval do
|
47
85
|
define_method(attr) do |*args|
|
48
86
|
case args.length
|
49
87
|
when 0
|
50
|
-
instance_variable_lookup
|
88
|
+
instance_variable_lookup var_name,
|
89
|
+
default: default,
|
90
|
+
default_from: default_from
|
51
91
|
when 1
|
52
92
|
instance_variable_set var_name, args[0]
|
53
93
|
else
|
@@ -63,6 +103,16 @@ module ClassAttrs
|
|
63
103
|
end
|
64
104
|
end
|
65
105
|
end
|
106
|
+
|
107
|
+
def class_attr_writer attr
|
108
|
+
var_name = "@#{ attr }".to_sym
|
109
|
+
|
110
|
+
singleton_class.class_eval do
|
111
|
+
define_method("#{ attr }=") do |value|
|
112
|
+
instance_variable_set var_name, value
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
66
116
|
end # module ClassMethods
|
67
117
|
|
68
118
|
# Extend the including class with {NRSER::Meta::ClassAttrs::ClassMethods}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module NRSER
|
2
|
+
|
3
|
+
# Eigenclass (Singleton Class)
|
4
|
+
# ========================================================================
|
5
|
+
#
|
6
|
+
class << self
|
7
|
+
|
8
|
+
# Deeply convert a {Hash} to an {OpenStruct}.
|
9
|
+
#
|
10
|
+
# @param [Hash] hash
|
11
|
+
#
|
12
|
+
# @return [OpenStruct]
|
13
|
+
#
|
14
|
+
# @raise [TypeError]
|
15
|
+
# If `hash` is not a {Hash}.
|
16
|
+
#
|
17
|
+
def to_open_struct hash, freeze: false
|
18
|
+
unless hash.is_a? Hash
|
19
|
+
raise TypeError,
|
20
|
+
"Argument must be hash (found #{ hash.inspect })"
|
21
|
+
end
|
22
|
+
|
23
|
+
_to_open_struct hash, freeze: freeze
|
24
|
+
end # #to_open_struct
|
25
|
+
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def _to_open_struct value, freeze:
|
30
|
+
result = case value
|
31
|
+
when OpenStruct
|
32
|
+
# Just assume it's already taken care of if it's already an OpenStruct
|
33
|
+
value
|
34
|
+
|
35
|
+
when Hash
|
36
|
+
OpenStruct.new(
|
37
|
+
map_values(value) { |k, v| _to_open_struct v, freeze: freeze }
|
38
|
+
)
|
39
|
+
|
40
|
+
when Array
|
41
|
+
value.map { |v| _to_open_struct v, freeze: freeze }
|
42
|
+
|
43
|
+
when Set
|
44
|
+
Set.new value.map { |v| _to_open_struct v, freeze: freeze }
|
45
|
+
|
46
|
+
else
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
if freeze
|
51
|
+
result.freeze
|
52
|
+
end
|
53
|
+
|
54
|
+
result
|
55
|
+
end # ._to_open_struct
|
56
|
+
# end private
|
57
|
+
|
58
|
+
end # class < self (Eigenclass)
|
59
|
+
|
60
|
+
end # module NRSER
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module NRSER; end
|
2
|
+
module NRSER::Refinements; end
|
3
|
+
|
4
|
+
# Instance methods that are mixed in to the refinements of many classes that
|
5
|
+
# include {Enumerable}, including {Array}, {Set}, {Hash} and {OpenStruct}.
|
6
|
+
#
|
7
|
+
# All of these just proxy to a {NRSER} module (static) method, so the
|
8
|
+
# functionality can be used on older Rubies that can't refine.
|
9
|
+
#
|
10
|
+
module NRSER::Refinements::Enumerable
|
11
|
+
|
12
|
+
# See {NRSER.map_values}
|
13
|
+
def map_values &block
|
14
|
+
NRSER.map_values self, &block
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
# See {NRSER.find_bounded}
|
19
|
+
def find_bounded bounds, &block
|
20
|
+
NRSER.find_bounded self, bounds, &block
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# See {NRSER.find_only}
|
25
|
+
def find_only &block
|
26
|
+
NRSER.find_only self, &block
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# See {NRSER.to_h_by}
|
31
|
+
def to_h_by &block
|
32
|
+
NRSER.to_h_by self, &block
|
33
|
+
end
|
34
|
+
|
35
|
+
# See {NRSER.enumerate_as_values}
|
36
|
+
def enumerate_as_values
|
37
|
+
NRSER.enumerate_as_values self
|
38
|
+
end
|
39
|
+
|
40
|
+
end # module NRSER::Refinements::Enumerable
|
41
|
+
|
@@ -4,4 +4,32 @@ module NRSER
|
|
4
4
|
NRSER.format_exception self
|
5
5
|
end
|
6
6
|
end
|
7
|
+
|
8
|
+
refine Exception.singleton_class do
|
9
|
+
|
10
|
+
# Create a new instance from the squished message.
|
11
|
+
#
|
12
|
+
# See {NRSER.squish}.
|
13
|
+
#
|
14
|
+
# @param [String] message
|
15
|
+
#
|
16
|
+
# @return [Exception]
|
17
|
+
#
|
18
|
+
def squished message
|
19
|
+
new message.squish
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create a new instance from the dedented message.
|
23
|
+
#
|
24
|
+
# See {NRSER.dedent}.
|
25
|
+
#
|
26
|
+
# @param [String] message
|
27
|
+
#
|
28
|
+
# @return [Exception]
|
29
|
+
#
|
30
|
+
def dedented message
|
31
|
+
new message.dedent
|
32
|
+
end
|
33
|
+
|
34
|
+
end # refine Exception.singleton_class
|
7
35
|
end # NRSER
|
@@ -1,5 +1,10 @@
|
|
1
|
+
require_relative './enumerable'
|
2
|
+
|
1
3
|
module NRSER
|
4
|
+
|
2
5
|
refine ::Hash do
|
6
|
+
include NRSER::Refinements::Enumerable
|
7
|
+
|
3
8
|
# See {NRSER.except_keys!}.
|
4
9
|
def except! *keys
|
5
10
|
NRSER.except_keys! self, *keys
|
@@ -28,11 +33,6 @@ module NRSER
|
|
28
33
|
end # #leaves
|
29
34
|
|
30
35
|
|
31
|
-
# See {NRSER.map_hash_values}.
|
32
|
-
def map_values &block
|
33
|
-
NRSER.map_hash_values self, &block
|
34
|
-
end
|
35
|
-
|
36
36
|
# See {NRSER.transform_keys!}
|
37
37
|
def transform_keys! &block
|
38
38
|
return enum_for(:transform_keys!) { size } unless block_given?
|
@@ -70,9 +70,11 @@ module NRSER
|
|
70
70
|
NRSER.stringify_keys self
|
71
71
|
end
|
72
72
|
|
73
|
+
|
73
74
|
# See {NRSER.map_hash_keys}
|
74
75
|
def map_keys &block
|
75
|
-
NRSER.
|
76
|
+
NRSER.map_keys self, &block
|
76
77
|
end
|
77
|
-
|
78
|
+
|
79
|
+
end # refine ::Hash
|
78
80
|
end # NRSER
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module NRSER
|
4
|
+
refine OpenStruct do
|
5
|
+
|
6
|
+
# Map values using {NRSER.map_values} into a new {OpenStruct} instance.
|
7
|
+
#
|
8
|
+
# @return [OpenStruct]
|
9
|
+
#
|
10
|
+
def map_values &block
|
11
|
+
self.class.new NRSER.map_values(self, &block)
|
12
|
+
end # #map_values
|
13
|
+
|
14
|
+
|
15
|
+
# See {NRSER.to_h_by}
|
16
|
+
def to_h_by &block
|
17
|
+
NRSER.to_h_by self, &block
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
refine OpenStruct.singleton_class do
|
23
|
+
|
24
|
+
# See {NRSER.to_open_struct}.
|
25
|
+
def from_h hash, freeze: false
|
26
|
+
NRSER.to_open_struct hash, freeze: freeze
|
27
|
+
end # .from
|
28
|
+
|
29
|
+
end
|
30
|
+
end # module NRSER
|