nrser 0.0.20 → 0.0.21
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/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
|