nrser 0.3.9 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +9 -19
  3. data/lib/nrser/char/special.rb +5 -5
  4. data/lib/nrser/core_ext/array.rb +36 -13
  5. data/lib/nrser/core_ext/enumerable.rb +1 -0
  6. data/lib/nrser/core_ext/enumerable/find_map.rb +1 -1
  7. data/lib/nrser/core_ext/hash/bury.rb +3 -0
  8. data/lib/nrser/core_ext/hash/extract_values_at.rb +2 -2
  9. data/lib/nrser/core_ext/method/full_name.rb +1 -1
  10. data/lib/nrser/core_ext/module/method_objects.rb +1 -1
  11. data/lib/nrser/core_ext/module/source_locations.rb +27 -15
  12. data/lib/nrser/core_ext/object/lazy_var.rb +1 -1
  13. data/lib/nrser/core_ext/pathname.rb +67 -12
  14. data/lib/nrser/core_ext/pathname/subpath.rb +86 -0
  15. data/lib/nrser/core_ext/string.rb +28 -1
  16. data/lib/nrser/core_ext/symbol.rb +11 -12
  17. data/lib/nrser/errors/README.md +154 -0
  18. data/lib/nrser/errors/attr_error.rb +146 -53
  19. data/lib/nrser/errors/count_error.rb +61 -12
  20. data/lib/nrser/errors/nicer_error.rb +42 -71
  21. data/lib/nrser/errors/value_error.rb +53 -58
  22. data/lib/nrser/functions.rb +0 -2
  23. data/lib/nrser/functions/enumerable.rb +5 -17
  24. data/lib/nrser/functions/enumerable/associate.rb +14 -5
  25. data/lib/nrser/functions/enumerable/find_all_map.rb +1 -1
  26. data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +1 -1
  27. data/lib/nrser/functions/hash/bury.rb +2 -12
  28. data/lib/nrser/functions/merge_by.rb +2 -2
  29. data/lib/nrser/functions/module/method_objects.rb +2 -2
  30. data/lib/nrser/functions/path.rb +185 -165
  31. data/lib/nrser/functions/path/normalized.rb +84 -0
  32. data/lib/nrser/functions/string.rb +4 -4
  33. data/lib/nrser/functions/text/README.md +4 -0
  34. data/lib/nrser/functions/text/format.rb +53 -0
  35. data/lib/nrser/functions/text/indentation.rb +6 -6
  36. data/lib/nrser/functions/text/word_wrap.rb +2 -2
  37. data/lib/nrser/functions/tree/map_leaves.rb +3 -3
  38. data/lib/nrser/functions/tree/map_tree.rb +2 -2
  39. data/lib/nrser/functions/tree/transform.rb +1 -18
  40. data/lib/nrser/gem_ext/README.md +4 -0
  41. data/lib/nrser/labs/README.md +8 -0
  42. data/lib/nrser/labs/config.rb +163 -0
  43. data/lib/nrser/labs/i8.rb +49 -159
  44. data/lib/nrser/labs/i8/struct.rb +167 -0
  45. data/lib/nrser/labs/i8/struct/hash.rb +140 -0
  46. data/lib/nrser/labs/i8/struct/vector.rb +149 -0
  47. data/lib/nrser/labs/i8/surjection.rb +211 -0
  48. data/lib/nrser/labs/lots/consumer.rb +19 -0
  49. data/lib/nrser/labs/lots/parser.rb +21 -1
  50. data/lib/nrser/labs/stash.rb +4 -4
  51. data/lib/nrser/log.rb +25 -21
  52. data/lib/nrser/log/appender/sync.rb +15 -11
  53. data/lib/nrser/log/formatters/color.rb +0 -3
  54. data/lib/nrser/log/formatters/mixin.rb +4 -4
  55. data/lib/nrser/log/logger.rb +54 -6
  56. data/lib/nrser/log/mixin.rb +2 -1
  57. data/lib/nrser/log/plugin.rb +6 -6
  58. data/lib/nrser/log/types.rb +46 -29
  59. data/lib/nrser/mean_streak.rb +0 -8
  60. data/lib/nrser/mean_streak/document.rb +1 -4
  61. data/lib/nrser/message.rb +3 -3
  62. data/lib/nrser/meta/README.md +4 -0
  63. data/lib/nrser/meta/lazy_attr.rb +2 -2
  64. data/lib/nrser/meta/source/location.rb +1 -1
  65. data/lib/nrser/props.rb +34 -3
  66. data/lib/nrser/props/class_methods.rb +2 -1
  67. data/lib/nrser/props/instance_methods.rb +9 -9
  68. data/lib/nrser/props/metadata.rb +4 -12
  69. data/lib/nrser/props/mutable/stash.rb +5 -2
  70. data/lib/nrser/props/prop.rb +10 -19
  71. data/lib/nrser/rspex.rb +1 -20
  72. data/lib/nrser/rspex/example_group/describe_attribute.rb +3 -0
  73. data/lib/nrser/rspex/example_group/describe_called_with.rb +9 -4
  74. data/lib/nrser/rspex/example_group/describe_case.rb +1 -0
  75. data/lib/nrser/rspex/example_group/describe_class.rb +2 -0
  76. data/lib/nrser/rspex/example_group/describe_group.rb +1 -1
  77. data/lib/nrser/rspex/example_group/describe_instance.rb +3 -1
  78. data/lib/nrser/rspex/example_group/describe_message.rb +1 -1
  79. data/lib/nrser/rspex/example_group/describe_method.rb +64 -30
  80. data/lib/nrser/rspex/example_group/describe_response_to.rb +1 -1
  81. data/lib/nrser/rspex/example_group/describe_section.rb +4 -1
  82. data/lib/nrser/rspex/example_group/describe_sent_to.rb +1 -1
  83. data/lib/nrser/rspex/example_group/describe_setup.rb +1 -0
  84. data/lib/nrser/rspex/example_group/describe_source_file.rb +1 -1
  85. data/lib/nrser/rspex/example_group/describe_spec_file.rb +4 -2
  86. data/lib/nrser/rspex/example_group/describe_when.rb +2 -1
  87. data/lib/nrser/rspex/example_group/describe_x.rb +5 -5
  88. data/lib/nrser/rspex/format.rb +0 -15
  89. data/lib/nrser/sugar/method_missing_forwarder.rb +3 -3
  90. data/lib/nrser/sys/env/path.rb +2 -28
  91. data/lib/nrser/types.rb +63 -12
  92. data/lib/nrser/types/README.md +76 -0
  93. data/lib/nrser/types/arrays.rb +192 -137
  94. data/lib/nrser/types/attributes.rb +269 -0
  95. data/lib/nrser/types/booleans.rb +134 -83
  96. data/lib/nrser/types/bounded.rb +110 -47
  97. data/lib/nrser/types/collections.rb +119 -0
  98. data/lib/nrser/types/combinators.rb +283 -196
  99. data/lib/nrser/types/doc/display_table.md +66 -0
  100. data/lib/nrser/types/eqiuvalent.rb +91 -0
  101. data/lib/nrser/types/errors/check_error.rb +5 -11
  102. data/lib/nrser/types/errors/from_string_error.rb +3 -3
  103. data/lib/nrser/types/factory.rb +287 -20
  104. data/lib/nrser/types/hashes.rb +227 -179
  105. data/lib/nrser/types/in.rb +73 -36
  106. data/lib/nrser/types/is.rb +67 -60
  107. data/lib/nrser/types/is_a.rb +141 -84
  108. data/lib/nrser/types/labels.rb +45 -16
  109. data/lib/nrser/types/maybe.rb +6 -3
  110. data/lib/nrser/types/nil.rb +64 -27
  111. data/lib/nrser/types/not.rb +92 -34
  112. data/lib/nrser/types/numbers.rb +224 -169
  113. data/lib/nrser/types/pairs.rb +113 -89
  114. data/lib/nrser/types/paths.rb +250 -137
  115. data/lib/nrser/types/responds.rb +167 -89
  116. data/lib/nrser/types/selector.rb +234 -0
  117. data/lib/nrser/types/shape.rb +136 -65
  118. data/lib/nrser/types/strings.rb +189 -63
  119. data/lib/nrser/types/symbols.rb +83 -33
  120. data/lib/nrser/types/top.rb +89 -0
  121. data/lib/nrser/types/tuples.rb +134 -98
  122. data/lib/nrser/types/type.rb +617 -505
  123. data/lib/nrser/types/when.rb +123 -98
  124. data/lib/nrser/types/where.rb +182 -91
  125. data/lib/nrser/version.rb +1 -1
  126. data/spec/lib/nrser/core_ext/pathname/subpath_spec.rb +22 -0
  127. data/spec/lib/nrser/errors/attr_error_spec.rb +68 -0
  128. data/spec/lib/nrser/errors/count_error_spec.rb +69 -0
  129. data/spec/lib/nrser/functions/path/normalize_path_spec.rb +35 -0
  130. data/spec/lib/nrser/functions/tree/map_tree_spec.rb +74 -96
  131. data/spec/lib/nrser/functions/tree/transform_spec.rb +11 -11
  132. data/spec/lib/nrser/labs/config_spec.rb +22 -0
  133. data/spec/lib/nrser/labs/i8/struct_spec.rb +39 -0
  134. data/spec/lib/nrser/types/display_spec.rb +50 -0
  135. data/spec/lib/nrser/types/paths_spec.rb +16 -10
  136. data/spec/lib/nrser/types/selector_spec.rb +125 -0
  137. data/spec/spec_helper.rb +4 -5
  138. metadata +105 -22
  139. data/lib/nrser/types/any.rb +0 -41
  140. data/lib/nrser/types/attrs.rb +0 -213
  141. data/lib/nrser/types/trees.rb +0 -42
@@ -6,6 +6,33 @@ require 'nrser/sys/env'
6
6
  # Extension methods for {String}
7
7
  #
8
8
  class String
9
+
10
+ # The method I alias as unary `~`, with a full-name so I can find it and
11
+ # such, I guess.
12
+ #
13
+ # It's a string formatter. Right now, it just calls {#squish}, but I would
14
+ # like to make it a bit smarter soon so it can be used on
15
+ # paragraph-structured text too.
16
+ #
17
+ # It's meant to be used with the `%{}` string quote form, because that allows
18
+ # multi-line strings, but nothing stopping it from being used elsewhere too.
19
+ #
20
+ # @example
21
+ #
22
+ # ~%{
23
+ # Hey there, here's some "stuff",
24
+ # and here's some MORE!
25
+ # }
26
+ # # => "Hey there, here's some \"stuff\", and here's some MORE!"
27
+ #
28
+ # @return [String]
29
+ #
30
+ def squiggle
31
+ squish
32
+ end
33
+
34
+ alias_method :~@, :squiggle
35
+
9
36
 
10
37
  def unblock
11
38
  NRSER.unblock self
@@ -72,7 +99,7 @@ class String
72
99
  #
73
100
  # Use {Regexp} ones at your own pleasure and peril.
74
101
  #
75
- # @param [String | Regexp] *prefixes
102
+ # @param [String | Regexp] prefixes
76
103
  # Strings behave as usual per the standard lib.
77
104
  #
78
105
  # Regexp sources are used to create a new Regexp with `\A` at the start -
@@ -1,13 +1,12 @@
1
1
  class Symbol
2
-
3
- # See {NRSER.retriever}.
4
- def to_retriever
5
- NRSER.retriever self
6
- end
7
-
8
-
9
- # Alias 'sender' methods to built-in {#to_proc} so symbols can behave like
10
- # arrays in this way
11
- alias_method :to_sender, :to_proc
12
-
13
- end # NRSER
2
+
3
+ # Proxy through to built-in {#to_proc} so symbols match the {Array#to_sender}
4
+ # API. I guess.
5
+ #
6
+ # @return [Proc]
7
+ # Accepts one argument and sends itself to that object, returning the
8
+ # result.
9
+ #
10
+ def to_sender; self.to_proc; end
11
+
12
+ end # class Symbol
@@ -0,0 +1,154 @@
1
+ About `nrser/errors`
2
+ ==============================================================================
3
+
4
+ {NRSER}'s error pseudo-module (everything in this directory is namespaced
5
+ directly under {NRSER} for brevity) is centered around the {NicerError}
6
+ mixin, which, well... tries to make working with errors a little nicer.
7
+
8
+ It includes:
9
+
10
+ 1. "Nice" extensions of some builtin error classes:
11
+ 1. {NRSER::AbstractMethodError} < {::NotImplementedError}
12
+ - For when an abstract method is mistakenly called.
13
+ 2. {NRSER::ArgumentError} < {::ArgumentError}
14
+ - A nice extensions of a familiar favorite.
15
+ 3. {NRSER::TypeError} < {::TypeError}
16
+ - A nice why to say they're not my type. Used extensively in
17
+ {NRSER::Types}, which is kind of like Tinder profiles for Ruby
18
+ objects.
19
+ 2. New "nice" extensions of {::StandardError}, and extensions of them:
20
+ 1. {NRSER::ValueError} < {::StandardError}>
21
+ - For when a problem is discovered with a value that is not an
22
+ argument, and the problem is not it's type.
23
+ 2. {NRSER::AttrError} < {NRSER::ValueError}
24
+ - Raise me when there's an issue with a attribute of an object.
25
+ 3. {NRSER::CountError} < {NRSER::AttrError}
26
+ - For when `#count` doesn't add up. I know, this one is weirdly
27
+ specific, but it solved something from what I remember.
28
+
29
+ You can check out the doc-strings to those various classes for details. For the
30
+ rest of this I'm going to focus on what the {NRSER::NicerError} mixin brings to
31
+ the table.
32
+
33
+ Let's check out some of the nicer features!
34
+
35
+
36
+ 1.) API Compatibility with Built-In Errors
37
+ ------------------------------------------------------------------------------
38
+
39
+ This one is important. {NRSER::NicerError} strictly enhances the standard Ruby
40
+ {Exception} API, meaning those classes can still be constructed with the
41
+
42
+ MyError.new( message_string )
43
+
44
+ form, and produce the error they should show at `MyError#message` and
45
+ `MyError#to_s`. Everything else is added on and optional, should you chose to
46
+ use it, though you will of course pay some slight performance penalty using
47
+ nicer errors in that way over the built-in classes.
48
+
49
+ I also want to stick with this policy for mixing classes unless they are very
50
+ specifically focused, like {NRSER::Types::CheckError}, which requires `value`
51
+ and `type` keyword arguments, and things like a hypothetical HTTP error that
52
+ requires the status code, etc., and want to extend the policy to cover the
53
+ {NRSER::NicerError} general construction form:
54
+
55
+ MyError.new *message, details:, **context
56
+
57
+ With general errors for general use, I've found it sucks to try and remember
58
+ various parameter forms and how they get stitched together when you're on a
59
+ roll or in a hurry, and I know it will impose even more overhead on people that
60
+ didn't write the library.
61
+
62
+ Errors should be easy as possible to use; they're already kind-of a pain as is.
63
+
64
+
65
+ 2.) Splat `message`
66
+ ------------------------------------------------------------------------------
67
+
68
+ Accept an variable amount of positional arguments as a `message` {Array}
69
+ instead of just a string, dumping non-string values and joining everything
70
+ together.
71
+
72
+ This lets you deal with printing/dumping all in one place instead of
73
+ adding `#to_s`, `#inspect`, `#pretty_inspect`, etc. all over the place.
74
+
75
+ Write things like:
76
+
77
+ MyError.new "The value", value, "sucks, it should be", expected
78
+
79
+ This should cut down the amount of typing when raising as well, which is
80
+ always welcome.
81
+
82
+ It also allows for a future where we get smarter about dumping things, offer
83
+ configuration options, switch on environments. For example, you might want to
84
+ produce rich messages with detailed dumps that take more time to format and
85
+ space to store while developing and produce concise messages that are cheap
86
+ to produce and store in production.
87
+
88
+ > Of course, in line with (1), you can always string-format elements of
89
+ > `message` yourself, and the resulting strings will be joined into the final
90
+ > message. You can also just pass a single string like Ruby's builtin
91
+ > exceptions, maintaining the same API.
92
+
93
+
94
+ 3.) "Extended" Messages - `details` and `context`
95
+ ------------------------------------------------------------------------------
96
+
97
+ The normal message that we talked about in (2) - that we call the *summary
98
+ message* or *super-message* (since it gets passed up to the built-in
99
+ {StandardError#initialize}) - is intended to be:
100
+
101
+ 1. Very concise
102
+ - A single line well under 80 characters if possible.
103
+
104
+ - This just seems like how Ruby exception messages were meant to be, I
105
+ guess, and in many situations it's all you would want or need
106
+ (production, just gets rescued anyways, there's no one there to read it,
107
+ etc.).
108
+
109
+ 2. Cheap to render and store.
110
+ - We may be trying to do lot very quickly on a production system.
111
+
112
+ However - especially when developing - it can be really nice to add
113
+ considerably more detail and feedback to errors.
114
+
115
+ To support this important use case as well, {NRSER::NicerError} introduces the
116
+ idea of an *extended message* that does not need to be rendered and
117
+ output along with the *summary/super-message*.
118
+
119
+ Extended messages are rendered on-demand, so systems that are not configured to
120
+ use it will pay a minimal cost for it's existence.
121
+
122
+ > See {NRSER::NicerError#extended_message}.
123
+
124
+ The extended message is composed of:
125
+
126
+ 1. Text *details*, optionally rendered via {Binding#erb} when a
127
+ binding is provided.
128
+
129
+ 2. A *context* of name and value pairs to dump.
130
+
131
+ Both are provided as optional keyword parameters to
132
+ {NRSER::NicerError#initialize}.
133
+
134
+ Those values may be accessed via {NRSER::NicerError#details} and
135
+ {NRSER::NicerError#context}, and rendered to strings
136
+
137
+
138
+ 3.) Default Message
139
+ ------------------------------------------------------------------------------
140
+
141
+ While (1) lets you know you should always be able to use the Ruby and nicer
142
+ construction forms on all but super-specific errors, {NRSER::NicerError} also
143
+ gives you the option of brevity with support for *default messages*, which
144
+ are constructed when no positional `message` arguments are passed to its
145
+ constructor.
146
+
147
+ Default messages presumably use the values of some well-known context values to
148
+ render the user-facing string, and degrade into some sort of complaint if
149
+ they're absent (someone could always be a wanker and call `MyError.new`, in
150
+ which case you're left with little resort but tell them so).
151
+
152
+ You can define default message behavior by overriding `#default_message` after
153
+ mixing-in {NRSER::NicerError}. Please practice caution in this - as well as
154
+ all error methods: don't cause errors when handling errors.
@@ -1,73 +1,166 @@
1
1
  # frozen_string_literal: true
2
+ # encoding: UTF-8
3
+
4
+ # Requirements
5
+ # ========================================================================
6
+
7
+ require_relative './value_error'
8
+
9
+
10
+ # Namespace
11
+ # ========================================================================
12
+
13
+ module NRSER
14
+
2
15
 
3
16
  # Raised when we expected `#count` to be something it's not.
4
17
  #
5
18
  # Extends {NRSER::ValueError}, and the {#value} must be the instance that
6
19
  #
7
- class NRSER::AttrError < NRSER::ValueError
8
-
9
- # Name of attribute that has invalid value.
20
+ class AttrError < ValueError
21
+
22
+ # @!method name?
23
+ # Is there an `:name` key in {#context}?
24
+ #
25
+ # @return [Boolean]
10
26
  #
11
- # @return [Symbol]
12
- #
13
- attr_reader :symbol
14
-
15
-
16
- # Actual invalid value of the subject's attribute.
27
+ # @!method name
28
+ # Name of attribute that has invalid value, which can be provided via
29
+ # the `:name` key in the {#context}.
30
+ #
31
+ # @return [Symbol | String]
17
32
  #
18
- # If not provided at construction, will be retrieved by sending {#symbol}
19
- # to {#subject} in {#initialize}.
33
+ def_context_delegator keys: :name
34
+
35
+
36
+ # @!method expected?
37
+ # Is there an `:expected` key in {#context}?
38
+ #
39
+ # @return [Boolean]
40
+ #
41
+ # @!method expected
42
+ # Optional information about what the attribute value was expected to be,
43
+ # which can be provided via the `:expected` key in {#context}.
44
+ #
45
+ # @return [Object]
20
46
  #
21
- # @return [Object]
47
+ def_context_delegator keys: :expected
48
+
49
+
50
+ # @!method initialize *message, **kwds
51
+ # Create a new {AttrError}.
52
+ #
53
+ # This method does nothing but call `super`. It's here only for doc's sake.
54
+ #
55
+ # @note
56
+ # If you provide the `:name` and `:value` keyword arguments, but *not*
57
+ # `:actual` then {#actual} will attempt to retrieve the attribute's value
58
+ # by
22
59
  #
23
- attr_reader :actual
24
-
25
-
26
- # An optional expected value to use in {#build_message}.
60
+ # value.public_send name
61
+ #
62
+ # This really *shouldn't* be problematic - if attempting to access a public
63
+ # attribute can cause serious side-effects, you may want to re-think your
64
+ # design. However, I still felt like I should note it here.
65
+ #
66
+ # The call is wrapped in a `rescue StandardError`, so you **don't** need
67
+ # to worry about anything mundane like an error being raised.
68
+ #
69
+ # @param [Array] message
70
+ # See {NicerError#initialize}.
71
+ #
72
+ # @param [Hash<Symbol, Object>] kwds
73
+ # Except as called out below, other keywords are passed up to
74
+ # {NicerError#initialize}.
75
+ #
76
+ # @option kwds [Symbol | String] :name
77
+ # The name of the attribute in question.
78
+ #
79
+ # @option kwds [Object] :value
80
+ # The value that has the bad attribute.
81
+ #
82
+ # @option kwds [Object | NRSER::Types::Type | String] :expected
83
+ # Encouraged to be one of:
84
+ #
85
+ # 1. The {Object} you wanted the attribute to respond with.
86
+ #
87
+ # 2. A {NRSER::Types::Type} satisfied by what you would have been satisfied
88
+ # with.
89
+ #
90
+ # 3. A {String} explanation of the condition.
91
+ #
92
+ # @option kwds [Object] :actual
93
+ # The actual attribute value.
94
+ #
95
+
96
+
97
+ # Tests if an 'actual' value was provided in the {#context}.
98
+ #
99
+ # @return [Boolean]
100
+ #
101
+ def actual?
102
+ context.key?( :actual ) || ( value? && name? && value.respond_to?( name ) )
103
+ rescue StandardError => error
104
+ false
105
+ end
106
+
107
+
108
+ # Get an optional actual value for the attribute, from `context[:actual]`
109
+ # if it exists or by sending {#name} to {#value} if it works.
110
+ #
111
+ # @return [nil]
112
+ # If {#context} does not have an `:actual` value and {#value} raises
113
+ # a {StandardError}.
27
114
  #
28
115
  # @return [Object]
29
- #
30
- attr_reader :expected
31
-
32
-
33
- # @param [Object] subject:
34
- # The object that has the invalid attribute value.
116
+ # The value of {#context}'s `:actual` key, if any, otherwise {#value}'s
117
+ # response to {#name}.
35
118
  #
36
- def initialize message = nil, symbol:, subject:, **options
37
- @symbol = symbol.to_sym
38
-
39
- @actual = if options.key?( :actual )
40
- options[:actual]
41
- else
42
- value.send @symbol
119
+ def actual
120
+ if context.key? :actual
121
+ context[ :actual ]
122
+ elsif value? && name?
123
+ value.public_send name
43
124
  end
44
-
45
- @has_expected = options.key? :expected
46
- @expected = options[:expected]
47
-
48
- super message, subject: subject
49
- end
50
-
51
- def has_expected?
52
- @has_expected
125
+ rescue StandardError => error
126
+ nil
53
127
  end
128
+
54
129
 
55
- def build_message
56
- headline = if has_expected?
57
- "#{ subject.class } object has invalid ##{ symbol }: " +
58
- "expected #{ expected }, found #{ actual }"
130
+ # Create a default message if none was provided.
131
+ #
132
+ # Uses whatever recognized {#context} values are present, falling back
133
+ # to {NicerError#default_message} if none are.
134
+ #
135
+ # @return [String]
136
+ #
137
+ def default_message
138
+ message = []
139
+
140
+ if value? && name?
141
+ message << format_message( value.class, "object", value.inspect,
142
+ "has invalid ##{ name } attribute" )
143
+ end
144
+
145
+ if expected?
146
+ message << format_message( "expected", expected )
147
+ end
148
+
149
+ if actual?
150
+ message << format_message( "found", actual )
151
+ end
152
+
153
+ if message.empty?
154
+ super
59
155
  else
60
- "#{ subject.class } object has invalid ##{ symbol } (found #{ actual })"
156
+ message.join ', '
61
157
  end
62
-
63
- binding.erb <<-END
64
- <%= headline %>
65
-
66
- Subject:
67
-
68
- <%= subject.pretty_inspect %>
69
-
70
- END
71
158
  end
72
159
 
73
- end # class NRSER::CountError
160
+ end # class AttrError
161
+
162
+
163
+ # /Namespace
164
+ # ========================================================================
165
+
166
+ end # module NRSER
@@ -1,19 +1,68 @@
1
1
  # frozen_string_literal: true
2
+ # encoding: UTF-8
3
+
4
+ # Requirements
5
+ # ========================================================================
6
+
7
+ # Project / Package
8
+ # ------------------------------------------------------------------------
9
+
10
+ require_relative './attr_error'
11
+
12
+
13
+ # Namespace
14
+ # ========================================================================
15
+
16
+ module NRSER
17
+
18
+
19
+ # Definitions
20
+ # ========================================================================
2
21
 
3
22
  # Raised when we expected `#count` to be something it's not.
4
23
  #
5
- # Extends {NRSER::ValueError}, and the {#value} must be the instance that
6
- #
7
24
  class NRSER::CountError < NRSER::AttrError
8
- def initialize message = nil, subject:, expected:, count: nil
9
- super message,
10
- subject: subject,
11
- symbol: :count,
12
- actual: (count || subject.count),
13
- expected: expected
25
+
26
+ # Create a new {CountError}.
27
+ #
28
+ # @param [Array] message
29
+ # See {NicerError#initialize}.
30
+ #
31
+ # @param [Hash<Symbol, Object>] kwds
32
+ # Except as called out below, other keywords are passed up to
33
+ # {NicerError#initialize}.
34
+ #
35
+ # @option kwds [Object] :value
36
+ # The value that has the bad `#count`.
37
+ #
38
+ # @option kwds [Integer | NRSER::Types::Type | String] :expected
39
+ # Encouraged to be one of:
40
+ #
41
+ # 1. An exact {Integer} that you were looking for.
42
+ #
43
+ # 2. A {NRSER::Types::Type} satisfied by what you would have been satisfied
44
+ # with.
45
+ #
46
+ # 3. A {String} explanation of the condition.
47
+ #
48
+ # @option kwds [Integer] :actual
49
+ # The actual count.
50
+ #
51
+ def initialize *message, **kwds
52
+ kwds[:actual] = kwds.delete( :count ) if kwds.key?( :count )
53
+ super *message, **kwds, name: :count
14
54
  end
55
+
56
+ # Alias for {#actual?}.
57
+ def count?; actual?; end
15
58
 
16
- def count
17
- actual
18
- end
19
- end # class NRSER::CountError
59
+ # Alias for {#actual}.
60
+ def count; actual; end
61
+
62
+ end # class CountError
63
+
64
+
65
+ # /Namespace
66
+ # ========================================================================
67
+
68
+ end # module NRSER