nrser 0.2.2 → 0.3.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.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
  3. data/lib/nrser/char.rb +0 -6
  4. data/lib/nrser/core_ext/array.rb +120 -0
  5. data/lib/nrser/core_ext/binding.rb +44 -0
  6. data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
  7. data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
  8. data/lib/nrser/core_ext/exception.rb +30 -0
  9. data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
  10. data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
  11. data/lib/nrser/core_ext/hash.rb +50 -0
  12. data/lib/nrser/core_ext/module/method_objects.rb +96 -0
  13. data/lib/nrser/core_ext/module/names.rb +69 -0
  14. data/lib/nrser/core_ext/module/source_locations.rb +214 -0
  15. data/lib/nrser/core_ext/module.rb +2 -0
  16. data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
  17. data/lib/nrser/core_ext/object.rb +46 -0
  18. data/lib/nrser/core_ext/open_struct.rb +6 -0
  19. data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
  20. data/lib/nrser/{ext → core_ext}/string.rb +6 -12
  21. data/lib/nrser/core_ext/symbol.rb +13 -0
  22. data/lib/nrser/core_ext/time.rb +46 -0
  23. data/lib/nrser/core_ext.rb +13 -0
  24. data/lib/nrser/errors/abstract_method_error.rb +150 -0
  25. data/lib/nrser/errors/argument_error.rb +42 -0
  26. data/lib/nrser/errors/nicer_error.rb +298 -72
  27. data/lib/nrser/errors/type_error.rb +46 -0
  28. data/lib/nrser/errors.rb +4 -53
  29. data/lib/nrser/ext/tree.rb +3 -0
  30. data/lib/nrser/functions/enumerable/associate.rb +6 -9
  31. data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
  32. data/lib/nrser/functions/enumerable.rb +1 -3
  33. data/lib/nrser/functions/exception.rb +1 -1
  34. data/lib/nrser/functions/hash.rb +0 -6
  35. data/lib/nrser/functions/merge_by.rb +2 -2
  36. data/lib/nrser/functions/module/method_objects.rb +77 -0
  37. data/lib/nrser/functions/module.rb +1 -2
  38. data/lib/nrser/functions/open_struct.rb +25 -35
  39. data/lib/nrser/functions/proc.rb +1 -6
  40. data/lib/nrser/functions/string/looks_like.rb +32 -1
  41. data/lib/nrser/functions/string.rb +1 -40
  42. data/lib/nrser/functions/text/lines.rb +2 -1
  43. data/lib/nrser/functions.rb +0 -1
  44. data/lib/nrser/graph/tsorter.rb +41 -0
  45. data/lib/nrser/labs/core_ext/binding.rb +37 -0
  46. data/lib/nrser/labs/stash.rb +372 -0
  47. data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
  48. data/lib/nrser/log/appender.rb +3 -0
  49. data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
  50. data/lib/nrser/log/formatters/mixin.rb +270 -0
  51. data/lib/nrser/{logging → log}/formatters.rb +0 -0
  52. data/lib/nrser/log/logger.rb +229 -0
  53. data/lib/nrser/log/mixin.rb +56 -0
  54. data/lib/nrser/log.rb +723 -0
  55. data/lib/nrser/message.rb +24 -3
  56. data/lib/nrser/meta/source/location.rb +158 -0
  57. data/lib/nrser/meta.rb +1 -1
  58. data/lib/nrser/props/class_methods.rb +118 -0
  59. data/lib/nrser/props/immutable/hash.rb +111 -0
  60. data/lib/nrser/props/immutable/hash_variable.rb +82 -0
  61. data/lib/nrser/props/immutable/instance_variables.rb +48 -0
  62. data/lib/nrser/props/immutable/vector.rb +107 -0
  63. data/lib/nrser/props/instance_methods.rb +184 -0
  64. data/lib/nrser/props/metadata.rb +359 -0
  65. data/lib/nrser/props/mutable/instance_variables.rb +60 -0
  66. data/lib/nrser/props/mutable/stash.rb +199 -0
  67. data/lib/nrser/{meta/props → props}/prop.rb +217 -112
  68. data/lib/nrser/props/storage/instance_variable.rb +85 -0
  69. data/lib/nrser/props/storage/instance_variables.rb +67 -0
  70. data/lib/nrser/props/storage/key.rb +88 -0
  71. data/lib/nrser/props.rb +9 -0
  72. data/lib/nrser/refinements/sugar.rb +41 -0
  73. data/lib/nrser/refinements/types.rb +2 -2
  74. data/lib/nrser/refinements.rb +14 -16
  75. data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
  76. data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
  77. data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
  78. data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
  79. data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
  80. data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
  81. data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
  82. data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
  83. data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
  84. data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
  85. data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
  86. data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
  87. data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
  88. data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
  89. data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
  90. data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
  91. data/lib/nrser/rspex/example_group/overrides.rb +66 -0
  92. data/lib/nrser/rspex/example_group.rb +20 -252
  93. data/lib/nrser/rspex/format.rb +83 -17
  94. data/lib/nrser/rspex.rb +4 -34
  95. data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
  96. data/lib/nrser/{env → sys/env}/path.rb +1 -2
  97. data/lib/nrser/{env.rb → sys/env.rb} +2 -1
  98. data/lib/nrser/sys.rb +5 -0
  99. data/lib/nrser/types/any.rb +36 -7
  100. data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
  101. data/lib/nrser/types/attrs.rb +68 -15
  102. data/lib/nrser/types/booleans.rb +95 -34
  103. data/lib/nrser/types/bounded.rb +12 -10
  104. data/lib/nrser/types/combinators.rb +74 -37
  105. data/lib/nrser/types/errors/check_error.rb +86 -0
  106. data/lib/nrser/types/errors/from_string_error.rb +82 -0
  107. data/lib/nrser/types/factory.rb +91 -0
  108. data/lib/nrser/types/hashes.rb +171 -26
  109. data/lib/nrser/types/in.rb +25 -12
  110. data/lib/nrser/types/is.rb +50 -18
  111. data/lib/nrser/types/is_a.rb +52 -33
  112. data/lib/nrser/types/labels.rb +6 -33
  113. data/lib/nrser/types/maybe.rb +12 -4
  114. data/lib/nrser/types/nil.rb +24 -4
  115. data/lib/nrser/types/not.rb +6 -16
  116. data/lib/nrser/types/numbers.rb +94 -57
  117. data/lib/nrser/types/pairs.rb +57 -57
  118. data/lib/nrser/types/paths.rb +112 -133
  119. data/lib/nrser/types/responds.rb +64 -74
  120. data/lib/nrser/types/shape.rb +29 -24
  121. data/lib/nrser/types/strings.rb +25 -17
  122. data/lib/nrser/types/symbols.rb +19 -17
  123. data/lib/nrser/types/trees.rb +18 -70
  124. data/lib/nrser/types/tuples.rb +36 -40
  125. data/lib/nrser/types/type.rb +342 -91
  126. data/lib/nrser/types/when.rb +40 -18
  127. data/lib/nrser/types/where.rb +94 -9
  128. data/lib/nrser/types.rb +72 -63
  129. data/lib/nrser/version.rb +1 -1
  130. data/lib/nrser.rb +18 -18
  131. data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
  132. data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
  133. data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
  134. data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
  135. data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
  136. data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
  137. data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
  138. data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
  139. data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
  140. data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
  141. data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
  142. data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
  143. data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
  144. data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
  145. data/spec/lib/nrser/refinements/array_spec.rb +2 -15
  146. data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
  147. data/spec/lib/nrser/refinements/set_spec.rb +2 -15
  148. data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
  149. data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
  150. data/spec/lib/nrser/types/array_spec.rb +8 -8
  151. data/spec/lib/nrser/types/paths_spec.rb +15 -18
  152. data/spec/spec_helper.rb +4 -0
  153. metadata +109 -69
  154. data/lib/nrser/ext/binding.rb +0 -36
  155. data/lib/nrser/ext/module.rb +0 -62
  156. data/lib/nrser/ext.rb +0 -8
  157. data/lib/nrser/functions/binding.rb +0 -76
  158. data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
  159. data/lib/nrser/functions/enumerable/map_values.rb +0 -94
  160. data/lib/nrser/functions/hash/deep_merge.rb +0 -57
  161. data/lib/nrser/functions/hash/except_keys.rb +0 -44
  162. data/lib/nrser/functions/hash/slice_keys.rb +0 -43
  163. data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
  164. data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
  165. data/lib/nrser/functions/hash/transform_keys.rb +0 -140
  166. data/lib/nrser/functions/module/methods.rb +0 -206
  167. data/lib/nrser/functions/module/source_locations.rb +0 -213
  168. data/lib/nrser/logging/appender.rb +0 -3
  169. data/lib/nrser/logging.rb +0 -353
  170. data/lib/nrser/meta/props/base.rb +0 -31
  171. data/lib/nrser/meta/props.rb +0 -357
  172. data/lib/nrser/refinements/array.rb +0 -133
  173. data/lib/nrser/refinements/binding.rb +0 -6
  174. data/lib/nrser/refinements/enumerator.rb +0 -5
  175. data/lib/nrser/refinements/exception.rb +0 -35
  176. data/lib/nrser/refinements/hash.rb +0 -150
  177. data/lib/nrser/refinements/module.rb +0 -5
  178. data/lib/nrser/refinements/object.rb +0 -42
  179. data/lib/nrser/refinements/open_struct.rb +0 -28
  180. data/lib/nrser/refinements/pathname.rb +0 -5
  181. data/lib/nrser/refinements/set.rb +0 -5
  182. data/lib/nrser/refinements/string.rb +0 -5
  183. data/lib/nrser/refinements/symbol.rb +0 -20
  184. data/lib/nrser/rspex/described.rb +0 -99
  185. data/spec/design/mapping_spec.rb +0 -42
  186. data/spec/lib/nrser/functions/hash_spec.rb +0 -41
  187. data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
  188. data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -1,110 +1,336 @@
1
+ # encoding: UTF-8
1
2
  # frozen_string_literal: true
2
3
 
4
+
3
5
  # Requirements
4
- # =======================================================================
6
+ # ========================================================================
5
7
 
6
8
  # Stdlib
7
- # -----------------------------------------------------------------------
9
+ # ------------------------------------------------------------------------
8
10
 
9
- # Deps
10
- # -----------------------------------------------------------------------
11
+ # Using {PP.pp} as default dumper.
12
+ require 'pp'
11
13
 
12
- # Project / Package
13
- # -----------------------------------------------------------------------
14
+ require 'nrser/core_ext/object/lazy_var'
14
15
 
15
16
 
16
17
  # Definitions
17
18
  # =======================================================================
18
19
 
19
- # A mixin for {Exception} and utilities to make errors nicer.
20
+ # A mixin for {Exception} and utilities to make life better... even when things
21
+ # go wrong.
22
+ #
23
+ # "Nicer" errors do a few things:
24
+ #
25
+ # 1. **`message` is a splat/`Array`**
26
+ #
27
+ # Accept an {Array} `message` instead of just a string, dumping non-string
28
+ # values and joining everything together.
29
+ #
30
+ # This lets you deal with printing/dumping all in one place instead of
31
+ # ad-hoc'ing `#to_s`, `#inspect`, `#pretty_inspect`, etc. all over the
32
+ # place (though you can still dump values yourself of course since string
33
+ # pass right through).
34
+ #
35
+ # Write things like:
36
+ #
37
+ # MyError.new "The value", value, "sucks, it should be", expected
38
+ #
39
+ # This should cut down the amount of typing when raising as well, which
40
+ # is always welcome.
41
+ #
42
+ # It also allows for a future where we get smarter about dumping things,
43
+ # offer configuration options, switch on environments (slow, rich dev
44
+ # versus fast, concise prod), etc.
45
+ #
46
+ # 2. **"Extended" Messages**
47
+ #
48
+ # The normal message that we talked about in (1) - that we call the
49
+ # *summary message* or *super-message* (since it gets passed up to the
50
+ # built-in Exception's `#initialize`) - is intended to be:
51
+ #
52
+ # 1. Very concise
53
+ # - A single line well under 80 characters if possible.
54
+ #
55
+ # - This just seems like how Ruby exception messages were meant to
56
+ # be, I guess, and in many situations it's all you would want or
57
+ # need (production, when it just gets rescued anyways,
58
+ # there's no one there to read it, etc.).
59
+ #
60
+ # 2. Cheap to render.
61
+ # - We may be trying to do lot very quickly on a production system.
62
+ #
63
+ # However - especially when developing - it can be really nice to add
64
+ # considerably more detail and feedback to errors.
65
+ #
66
+ # To support this important use case as well, `NicerError` introduces the
67
+ # idea of an *extended message* that does not need to be rendered and
68
+ # output along with the *summary/super-message*.
69
+ #
70
+ # It's rendering is done on-demand, so systems that are not configured to
71
+ # use it will pay a minimal cost for it's existence.
72
+ #
73
+ # > See {#extended_message}.
74
+ #
75
+ # The extended message is composed of:
76
+ #
77
+ # 1. Text *details*, optionally rendered via {Binding.erb} when a
78
+ # binding is provided.
79
+ #
80
+ # 2. A *context* of name and value pairs to dump.
81
+ #
82
+ # Both are provided as optional keyword parameters to {#initialize}.
20
83
  #
21
84
  module NRSER::NicerError
22
85
 
86
+ # Constants
87
+ # ========================================================================
88
+
89
+ # Default column width
90
+ DEFAULT_COLUMN_WIDTH = 78
91
+
23
92
 
24
- # TODO document `context` attribute.
93
+ # Module Methods
94
+ # ==========================================================================
95
+
96
+ # Column width to format for (just summary/super-message at the moment).
97
+ #
98
+ # @todo
99
+ # Implement terminal width detection like Thor?
100
+ #
101
+ # @return [Fixnum]
102
+ # Positive integer.
25
103
  #
26
- # @return [Hash<Symbol, V>]
27
- #
28
- attr_reader :context
104
+ def self.column_width
105
+ DEFAULT_COLUMN_WIDTH
106
+ end
29
107
 
30
108
 
31
- # @todo Document render_message method.
109
+ # Construct a nicer error.
32
110
  #
33
- # @param [type] arg_name
34
- # @todo Add name param description.
111
+ # @param [Array] *message
112
+ # Main message segments.
35
113
  #
36
- # @return [return_type]
37
- # @todo Document return value.
114
+ # @param [Binding?] binding:
115
+ # When provided any details string will be rendered using it's
116
+ # {Binding#erb} method.
38
117
  #
39
- def self.render_message message,
40
- context: {},
41
- add_context: true,
42
- &get_extended_message
43
-
44
- # 1. Figure out if `message` is just the "short message" (single line)
45
- # or if it's "old-style" where it's just the whole thing.
46
-
47
- message_lines = message.lines
118
+ # @param [nil | String | Proc<()=>String> | #to_s] details:
119
+ # Additional text details to add to the extended message. When:
120
+ #
121
+ # 1. `nil` - no details will be added.
122
+ #
123
+ # 2. `String` - the value will be used. If `binding:` is provided, it
124
+ # will be rendered against it as ERB.
125
+ #
126
+ # 3. `Proc<()=>String>` - if and when an extended message is needed
127
+ # the proc will be called, and the resulting string will be used
128
+ # as in (2).
129
+ #
130
+ # 4. `#to_s` - catch all; if and when an extended message is needed
131
+ # `#to_s` will be called on the value and the result will be used
132
+ # as in (2).
133
+ #
134
+ # @param [Hash<Symbol, VALUE>] **context
135
+ # Any additional names and values to dump with an extended message.
136
+ #
137
+ def initialize *message,
138
+ binding: nil,
139
+ details: nil,
140
+ **context
141
+ @binding = binding
142
+ @context = context
143
+ @details = details
48
144
 
49
- if message_lines.length > 1
50
- message_lines = NRSER.dedent message_lines, return_lines: true
51
- short_message = message_lines.first.chomp
52
- extended_message_lines = message_lines.rest
53
- else
54
- short_message = message
55
- extended_message_lines = nil
56
- end
145
+ message = default_message if message.empty?
146
+ super_message = format_message *message
57
147
 
58
- # Ok, `short_message` is a single line string
59
- # `extended_message_lines` is an array of string lines or `nil`
148
+ super super_message
149
+ end # #initialize
150
+
151
+
152
+ # Format a segment of the error message.
153
+ #
154
+ # Strings are simply returned. Other things are inspected (for now).
155
+ #
156
+ # @param [Object] segment
157
+ # The segment.
158
+ #
159
+ # @return [String]
160
+ # The formatted string for the segment.
161
+ #
162
+ def format_message_segment segment
163
+ return segment if String === segment
60
164
 
61
- # 2.
62
-
63
- if get_extended_message
64
- got_extended_message = if get_extended_message.arity == 0
65
- get_extended_message.call
165
+ # TODO Do better!
166
+ segment.inspect
167
+ end # #format_message_segment
168
+
169
+
170
+ # Format the main message by converting args to strings and joining them.
171
+ #
172
+ # @param [Array] *message
173
+ # Message segments.
174
+ #
175
+ # @return [String]
176
+ # Formatted and joined message ready to pass up to the built-in
177
+ # exception's `#initialize`.
178
+ #
179
+ def format_message *message
180
+ message.map( &method( :format_message_segment ) ).join( ' ' )
181
+ end
182
+
183
+
184
+ # Main message to use when none provided to {#initialize}.
185
+ #
186
+ # @return [String]
187
+ #
188
+ def default_message
189
+ "(no message)"
190
+ end
191
+
192
+
193
+ # Any additional context values to add to extended messages provided to
194
+ # {#initialize}.
195
+ #
196
+ # @return [Hash<Symbol, *>]
197
+ #
198
+ def context
199
+ @context
200
+ end
201
+
202
+
203
+ def details
204
+ @details
205
+ end
206
+
207
+
208
+ # Render details (first time only, then cached) and return the string.
209
+ #
210
+ # @return [String?]
211
+ #
212
+ def details_section
213
+ lazy_var :@details_section do
214
+ # No details if we have nothing to work with
215
+ if details.nil?
216
+ nil
66
217
  else
67
- get_extended_message.call context
218
+ contents = case details
219
+ when Proc
220
+ details.call
221
+ when String
222
+ details
223
+ else
224
+ details.to_s
225
+ end
226
+
227
+ if contents.empty?
228
+ nil
229
+ else
230
+ if @binding
231
+ contents = binding.erb contents
232
+ end
233
+
234
+ "# Details\n\n" + contents
235
+ end
68
236
  end
69
-
70
- got_extended_message_lines = NRSER.dedent \
71
- got_extended_message,
72
- return_lines: true
73
-
74
- if extended_message_lines
75
- extended_message_lines += [
76
- "\n",
77
- *got_extended_message_lines
78
- ]
237
+ end
238
+ end
239
+
240
+
241
+ # @return [String?]
242
+ #
243
+ def context_section
244
+ lazy_var :@context_section do
245
+ if context.empty?
246
+ nil
79
247
  else
80
- extended_message_lines = got_extended_message_lines
248
+ "# Context:\n\n" + context.map { |name, value|
249
+ name_str = name.to_s
250
+ value_str = PP.pp \
251
+ value,
252
+ ''.dup,
253
+ (NRSER::NicerError.column_width - name_str.length - 2)
254
+
255
+ if value_str.lines.count > 1
256
+ "#{ name_str }:\n\n#{ value_str.indent 4 }\n"
257
+ else
258
+ "#{ name_str }: #{ value_str }\n"
259
+ end
260
+ }.join
81
261
  end
82
262
  end
83
-
84
- if add_context
85
- extended_message_lines += [
86
- "Context:\n",
87
- "\n"
88
- "\n <%= %>"
89
- ]
90
- end
263
+ end
264
+
265
+
266
+ # Return the extended message, rendering if necessary (cached after first
267
+ # call).
268
+ #
269
+ # @return [String]
270
+ # Will be empty if there is no extended message.
271
+ #
272
+ def extended_message
273
+ @extended_message ||= begin
274
+ sections = []
275
+
276
+ sections << details_section unless details_section.nil?
277
+ sections << context_section unless context_section.nil?
91
278
 
92
- end # .render_message
279
+ joined = sections.join "\n\n"
280
+ end
281
+ end
93
282
 
94
283
 
95
- # @todo Document initialize method.
284
+ # Should we add the extended message to {#to_s} output?
96
285
  #
97
- # @param [type] arg_name
98
- # @todo Add name param description.
286
+ # @todo
287
+ # Just returns `true` for now... should be configurable in the future.
99
288
  #
100
- # @return [return_type]
101
- # @todo Document return value.
289
+ # @return [Boolean]
102
290
  #
103
- def initialize message,
104
- context: {},
105
- add_context: true,
106
- &
107
- @context = context
108
- end # #initialize
291
+ def add_extended_message?
292
+ true
293
+ end
294
+
295
+
296
+ # Get the message or the extended message.
297
+ #
298
+ # @note
299
+ # This is a bit weird, having to do with what I can tell about the
300
+ # built-in errors and how they handle their message - they have *no*
301
+ # instance variables, and seem to rely on `#to_s` to get the message
302
+ # out of C-land, however that works.
303
+ #
304
+ # {Exception#message} just forwards here, so I overrode that with
305
+ # {#message} to just get the *summary/super-message* from this method.
306
+ #
307
+ # @param [Boolean?] extended:
308
+ # Flag to explicitly control summary/super or extended message:
309
+ #
310
+ # 1. `nil` - call {#add_extended_message?} to decide (default).
311
+ # 2. `false` - return just the *summary/super-message*.
312
+ # 3. `true` - always add the *extended message* (unless it's empty).
313
+ #
314
+ # @return [String]
315
+ #
316
+ def to_s extended: nil
317
+ # The way to get the superclass' message
318
+ message = super()
319
+
320
+ # If `extended` is explicitly `false` then just return that
321
+ return message if extended == false
322
+
323
+ # Otherwise, see if the extended message was explicitly requested,
324
+ # of if we're configured to provide it as well.
325
+ #
326
+ # Either way, don't add it it's empty.
327
+ #
328
+ if (extended || add_extended_message?) &&
329
+ !extended_message.empty?
330
+ message + "\n\n" + extended_message
331
+ else
332
+ message
333
+ end
334
+ end
109
335
 
110
336
  end # module NRSER::NicerError
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Deps
11
+ # -----------------------------------------------------------------------
12
+
13
+ # Project / Package
14
+ # -----------------------------------------------------------------------
15
+
16
+ require_relative './nicer_error'
17
+
18
+
19
+ # Declarations
20
+ # =======================================================================
21
+
22
+
23
+ # Definitions
24
+ # =======================================================================
25
+
26
+
27
+ # Extension of {::ArgumentError} that includes {NRSER::NicerError} and
28
+ # supports optional
29
+ #
30
+ class NRSER::TypeError < ::TypeError
31
+
32
+ include NRSER::NicerError
33
+
34
+
35
+ # Instance Methods
36
+ # ========================================================================
37
+
38
+ # def expected
39
+ # context[:expected]
40
+ # end
41
+
42
+ # def default_message
43
+ # ["Expected", name, ""]
44
+ # end
45
+
46
+ end # class NRSER::ArgumentError
data/lib/nrser/errors.rb CHANGED
@@ -13,6 +13,9 @@
13
13
  require_relative './errors/value_error'
14
14
  require_relative './errors/attr_error'
15
15
  require_relative './errors/count_error'
16
+ require_relative './errors/argument_error'
17
+ require_relative './errors/type_error'
18
+ require_relative './errors/abstract_method_error'
16
19
 
17
20
 
18
21
  module NRSER
@@ -22,58 +25,6 @@ module NRSER
22
25
  class ConflictError < StandardError; end
23
26
 
24
27
 
25
- # Extension of Ruby's {NotImplementedError} to provide a useful message
26
- # and convenient constructor for abstract methods.
27
- #
28
- # @example
29
- #
30
- # def f
31
- # raise NRSER::AbstractMethodError.new( self, __method__ )
32
- #
33
- #
34
- class AbstractMethodError < NotImplementedError
35
-
36
- # Construct a new `AbstractMethodError`.
37
- #
38
- # @param [Object] instance
39
- # Instance that invoked the abstract method.
40
- #
41
- # @param [Symbol | String] method_name
42
- # Name of abstract method.
43
- #
44
- def initialize instance, method_name
45
- @instance = instance
46
- @method_name = method_name
47
- @method = instance.method @method_name
48
-
49
- message = if @method.owner == instance.class
50
- NRSER.dedent <<-END
51
- Method #{ @method.owner.name }##{ @method_name } is abstract, meaning
52
- #{ @method.owner.name } is an abstract class and the invoking
53
- instance #{ @instance } should NOT have been constructed.
54
- END
55
- else
56
- NRSER.squish <<-END
57
- Method #{ @method.owner.name }##{ @method_name } is abstract and
58
- has not been implemented in invoking class #{ @instance.class }.
59
-
60
- If you *are* developing the invoking class #{ @instance.class } it
61
- (or a parent class between it and #{ @method.owner.name }) must
62
- implement ##{ @method_name }.
63
-
64
- If you *are not* developing #{ @instance.class } it should be treated
65
- as an abstract base class and should NOT be constructed. You need to
66
- find a subclass of #{ @instance.class } to instantiate or write
67
- your own.
68
- END
69
- end
70
-
71
- super message
72
- end # #initialize
73
-
74
- end # class AbstractMethodError
75
-
76
-
77
28
  # A wrapper error around a list of other errors.
78
29
  #
79
30
  class MultipleErrors < StandardError
@@ -103,7 +54,7 @@ module NRSER
103
54
  headline = "#{ errors.count } error(s) occurred - #{ class_counts }"
104
55
  end
105
56
 
106
- message = NRSER.erb binding, <<-END
57
+ message = binding.erb <<-END
107
58
  <%= headline %>
108
59
 
109
60
  <% errors.each_with_index do |error, index| %>
@@ -1,3 +1,6 @@
1
+ module NRSER::Ext; end
2
+
3
+
1
4
  # Instance methods that are refined in to the Ruby built-ins that we consider
2
5
  # trees: {Array}, {Hash} and {OpenStruct}.
3
6
  #
@@ -11,11 +11,11 @@ module NRSER
11
11
  # get it's key, raising an error if multiple entries map to the same key.
12
12
  #
13
13
  # @example Basic usage
14
- # ['a', :b].to_h_by &:class
14
+ # ['a', :b].assoc_by &:class
15
15
  # # => {String=>"a", Symbol=>:b}
16
16
  #
17
17
  # @example Conflict error
18
- # [:a, :b].to_h_by &:class
18
+ # [:a, :b].assoc_by &:class
19
19
  # # NRSER::ConflictError: Key Symbol is already in results with value:
20
20
  # #
21
21
  # # :a
@@ -37,7 +37,7 @@ module NRSER
37
37
  key = block.call element
38
38
 
39
39
  if result.key? key
40
- raise NRSER::ConflictError.new erb binding, <<-END
40
+ raise NRSER::ConflictError.new binding.erb <<-END
41
41
  Key <%= key.inspect %> is already in results with value:
42
42
 
43
43
  <%= result[key].pretty_inspect %>
@@ -47,10 +47,7 @@ module NRSER
47
47
 
48
48
  result[key] = element
49
49
  }
50
- end # .to_h_by
51
-
52
- singleton_class.send :alias_method, :to_h_by, :assoc_by
53
-
50
+ end # .assoc_by
54
51
 
55
52
 
56
53
  # Create a {Hash} mapping the entries in `enum` to the value returned by
@@ -68,7 +65,7 @@ module NRSER
68
65
  value = if hash.key? entry
69
66
  case on_conflict
70
67
  when :raise
71
- raise NRSER::ConflictError.new erb binding, <<-END
68
+ raise NRSER::ConflictError.new binding.erb <<-END
72
69
  Entry <%= entry %> appears more than once in `enum`
73
70
 
74
71
  This would cause conflict in the resulting {Hash}.
@@ -97,7 +94,7 @@ module NRSER
97
94
 
98
95
  hash[entry] = value
99
96
  }
100
- end # .map_to
97
+ end # .assoc_to
101
98
 
102
99
 
103
100
  end # module NRSER
@@ -1,6 +1,5 @@
1
1
  require_relative './include_slice/array_include_slice'
2
2
 
3
- using NRSER
4
3
 
5
4
  module NRSER
6
5
 
@@ -54,11 +53,11 @@ module NRSER
54
53
  raise TypeError.new binding.erb <<-END
55
54
  Both `enum` and `slice` must be {Enumerable}
56
55
 
57
- enum (<%= enum.class.name %>):
56
+ enum (<%= enum.class.safe_name %>):
58
57
 
59
58
  <%= enum.pretty_inspect %>
60
59
 
61
- slice (<%= slice.class.name %>):
60
+ slice (<%= slice.class.safe_name %>):
62
61
 
63
62
  <%= slice.pretty_inspect %>
64
63
 
@@ -1,8 +1,6 @@
1
- require_relative './enumerable/find_map'
2
1
  require_relative './enumerable/find_all_map'
3
2
  require_relative './enumerable/include_slice'
4
3
  require_relative './enumerable/associate'
5
- require_relative './enumerable/map_values'
6
4
 
7
5
  module NRSER
8
6
 
@@ -64,7 +62,7 @@ module NRSER
64
62
  NRSER::Types.
65
63
  length(bounds).
66
64
  check(enum.find_all &block) { |type:, value:|
67
- erb binding, <<-END
65
+ binding.erb <<-END
68
66
 
69
67
  Length of found elements (<%= value.length %>) FAILED to
70
68
  satisfy <%= type.to_s %>.
@@ -11,7 +11,7 @@ module NRSER
11
11
  # @return [String]
12
12
  #
13
13
  def self.format_exception e
14
- "#{ e.message } (#{ e.class }):\n #{ e.backtrace.join("\n ") }"
14
+ "#{ e.to_s } (#{ e.class }):\n #{ e.backtrace.join("\n ") }"
15
15
  end
16
16
 
17
17
  end # module NRSER
@@ -3,11 +3,5 @@
3
3
 
4
4
  # Project / Package
5
5
  # -----------------------------------------------------------------------
6
- require_relative './hash/except_keys'
7
- require_relative './hash/transform_keys'
8
- require_relative './hash/symbolize_keys'
9
- require_relative './hash/stringify_keys'
10
- require_relative './hash/slice_keys'
11
6
  require_relative './hash/guess_label_key_type'
12
7
  require_relative './hash/bury'
13
- require_relative './hash/deep_merge'
@@ -21,8 +21,8 @@ module NRSER
21
21
  # Final array of merged hashes. Don't depend on order.
22
22
  #
23
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 )
24
+ updates.reduce( assoc_by current, &merge_key ) { |result, update|
25
+ result.deep_merge! assoc_by( update, &merge_key )
26
26
  }.values
27
27
  end # .merge_by
28
28