constrain 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff3fb59b6d713b01843aa67e4e90855e58f99b1fcffa8ff27ae66b53987d9672
4
- data.tar.gz: 98237076729ee99035e1af426308f12ef36963879950287f107486ae0485e061
3
+ metadata.gz: ceffc61373ff30143743c0cca412f43abe64bbb6e012722c1ba2ab5035fe939b
4
+ data.tar.gz: ed70c819e47438f269c1d58d1291d4cde4eef22fc73049fd67c4b4d1b9c3da7a
5
5
  SHA512:
6
- metadata.gz: 533a2c7486903550fa42c3f349417130a8dd69642adf6d2e27599bd9f5e4b6be3fca0dcfcc58370cf4d64169952e06df5a0ad76603d424741f0c7846301f66ac
7
- data.tar.gz: 95ee72d76e6ccfdd7faffd971214ecc6b171ab1a58debfd5a6a043a0764e8f154a910a7086399363a4bc88e94406a7a048f5efa32cadf5c1d8ded2e1725fcc37
6
+ metadata.gz: 94aeb7517bb00357f29bedf15a0b509fcefb28664e9c31e59f3a592e64c69da601a1e379cfeb473e7af590f69d1879c0dded102e55f159ecb8ef5dd8d8a84f58
7
+ data.tar.gz: e1eb0ec5ad04063965262a6be821027859a61c5fa42ec3b97da18d2e95e5193b95a8f96e4bf3a222bf866bd8e0c38579f7d50dd5380b305b3cc3badb66eceebf
data/README.md CHANGED
@@ -22,7 +22,7 @@ f("Hello", "world") # Boom
22
22
  It is intended to be an aid in development only and to be deactivated in
23
23
  production (TODO: Make it possible to deactivate)
24
24
 
25
- Constrain works with ruby-2 (and maybe ruby-3)
25
+ Constrain works with ruby-3
26
26
 
27
27
  ## Usage
28
28
 
@@ -35,15 +35,24 @@ require 'constrain'
35
35
  include Constrain
36
36
 
37
37
  def f(a, b, c)
38
- constrain a, Integer # An integer
39
- constrain b, [Symbol, String] => Integer # Hash with String or Symbol keys
40
- constrain c, [String], NilClass # Array of strings or nil
38
+ constrain a, Integer # An integer
39
+ constrain b, { [Symbol, String] => Integer } # Hash with String or Symbol keys
40
+ constrain c, [String], NilClass # Array of strings or nil
41
41
  ...
42
42
  end
43
43
  ```
44
44
 
45
- The alternative is to include the constrain Module in a common root class to
46
- have it available in all child classes
45
+ Constrain only defines the methods \#constrain and \#constrain? so it is
46
+ acceptible in most cases. An alternative is to include the constrain module
47
+ in a common root class to have it available in all child classes:
48
+
49
+ ```ruby
50
+ class BaseClass
51
+ include Constrain
52
+ ...
53
+ end
54
+ ```
55
+
47
56
 
48
57
  ## Methods
49
58
 
@@ -103,11 +112,11 @@ Simple values are compared to the expected result using the #=== operator. This
103
112
  means you can use regular expressions too:
104
113
 
105
114
  ```ruby
106
- # Simple email regular expression (https://stackoverflow.com/a/719543)
107
- EMAIL_RE = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9.-]+$/
115
+ # Simple (!) email address regular expression (https://stackoverflow.com/a/719543)
116
+ EMAIL_ADDRESS_RE = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9.-]+$/
108
117
 
109
- def email(address)
110
- constrain address, EMAIL_RE
118
+ def send_email(address)
119
+ constrain address, EMAIL_ADDRESS_RE
111
120
  ...
112
121
  end
113
122
  ```
@@ -164,8 +173,8 @@ Hashes match if value is a hash and every key/value pair match one of the given
164
173
  key-class/value-class expressions:
165
174
 
166
175
  ```ruby
167
- constrain({"str" => 42}, String => Integer) # Success
168
- constrain({"str" => 42}, String => String) # Failure
176
+ constrain({"str" => 42}, { String => Integer }) # Success
177
+ constrain({"str" => 42}, { String => String }) # Failure
169
178
  ```
170
179
 
171
180
  Note that the parenthesis are needed because otherwise the Ruby parser would
@@ -177,15 +186,15 @@ element so that `[String, Symbol]` matches either a String or a Symbol value
177
186
  while `[String]` matches an array of String objects:
178
187
 
179
188
  ```ruby
180
- constrain({ sym: 42 }, [Symbol, String] => Integer) # Success
181
- constrain({ [sym] => 42 }, [Symbol, String] => Integer) # Failure
189
+ constrain({ sym: 42 }, { [Symbol, String] => Integer }) # Success
190
+ constrain({ [sym] => 42 }, { [Symbol, String] => Integer }) # Failure
182
191
  ```
183
192
 
184
193
  To specify an array of Symbol or String objects in hash keys or values, make
185
194
  sure the list expression is enclosed in an array:
186
195
 
187
196
  ```ruby
188
- constrain({ [sym] => 42 }, [[Symbol, String]] => Integer) # Success
197
+ constrain({ [sym] => 42 }, { [[Symbol, String]] => Integer }) # Success
189
198
  ```
190
199
 
191
200
  #### nil, true and false
@@ -245,6 +254,38 @@ include business logic that should be kept in the production code. Constrain is
245
254
  only thouhgt of as a tool to catch developer errors - not errors that stem from
246
255
  corrupted data
247
256
 
257
+ ## Other uses
258
+
259
+ Constrain can be used to type-check complex structures like YAML documents:
260
+
261
+ ```ruby
262
+ # A YAML value
263
+ value = {
264
+ "str" => "a",
265
+ "int" => 42,
266
+ "arr" => [1, 2],
267
+ "hash" => {
268
+ "key1" => "b",
269
+ "key2" => 42
270
+ }
271
+ }
272
+
273
+ # Type description
274
+ type = {
275
+ "str" => String,
276
+ "int" => Integer,
277
+ "arr" => [Integer],
278
+ "hash" => {
279
+ "key1" => [String, Integer],
280
+ "key2" => [String, Integer]
281
+ }
282
+ }
283
+
284
+ puts constrain?(value, type) ? "yes" : "no" # Outputs 'yes'
285
+ value["str"] = 42
286
+ puts constrain?(value, type) ? "yes" : "no" # Outputs 'no'
287
+ ```
288
+
248
289
  ## Installation
249
290
 
250
291
  Add this line to your application's Gemfile:
data/TODO CHANGED
@@ -1,14 +1,25 @@
1
1
 
2
+ o A constrain_class method that allows for inherited-from tests
3
+ o Allow single-argument boolean expressions: 'constrain !a.empty?'
4
+ o This seems to cause a stack error: 'constrain some-hash, Symbol'
5
+ o Allow range as value expressions. And REs!
2
6
  o Use | to create class-or expressions
3
- o Old: Class | Class syntax
7
+ o Class | Class syntax
8
+ o Will solve problem with [String, Integer] as a String/Integer vs. An array
9
+ of strings and integers
4
10
  o Use & to construct tuple expressions
5
- o Old: A tuple method: "Symbol => constrain.tuple(String, Integer)"
11
+ o Class & Class (doesn't look good - maybe Class + Class ?)
12
+ o Alt: A tuple method: "Symbol => constrain.tuple(String, Integer)"
6
13
  o Better error message for 'constrain EXPR'
7
14
  o Explain that 'constrain EXPR' can be used for 'constrain SomeClass < AnotherClass'
8
15
  o Match ranges and regular expressions
9
16
  o An array and hash method: "Symbol => constrain.array(Integer), String => constrain.hash(Symbol, Integer)"
17
+ Nope. Solved by | syntax
10
18
  o Constrained attributes: constrain_reader, constrain_writer, constrain_accessor:
11
- o Messages should include info about the unexpected element type in arrays (and maybe more): "Expected [#<PgGraph::Data::Record:public.pings[1] {id: 1, name: 'Ping A'}>, #<PgGraph::Data::Record:public.pings[2] {id: 2, name: 'Ping B'}>, nil] to match [PgGraph::Data::Record]
19
+ o Messages should include info about the unexpected element type in arrays (and
20
+ maybe more): "Expected [#<PgGraph::Data::Record:public.pings[1] {id: 1, name:
21
+ 'Ping A'}>, #<PgGraph::Data::Record:public.pings[2] {id: 2, name: 'Ping B'}>,
22
+ nil] to match [PgGraph::Data::Record]
12
23
 
13
24
  + constrain value, class-expr, "Error message"
14
25
  + Check against values: 'constrain arg, :one_value, :another_value, 1, 2, 3'
@@ -1,3 +1,3 @@
1
1
  module Constrain
2
- VERSION = "0.9.0"
2
+ VERSION = "0.10.0"
3
3
  end
data/lib/constrain.rb CHANGED
@@ -54,12 +54,8 @@ module Constrain
54
54
  # unwind is automatically incremented by one because ::do_constrain is always
55
55
  # called from one of the other constrain methods
56
56
  #
57
- def self.do_constrain(value, *exprs, unwind: 0, message: nil, **opts)
58
- opts.keys.empty? || opts.keys == [:not] or raise ArgumentError
57
+ def self.do_constrain(value, *exprs, unwind: 0, message: nil)
59
58
  unwind += 1
60
- not_argument = opts.key?(:not)
61
- not_value = opts[:not]
62
-
63
59
  begin
64
60
  if exprs.empty?
65
61
  value or raise MatchError.new(value, [], message: message, unwind: unwind)
@@ -67,10 +63,6 @@ module Constrain
67
63
  exprs.any? { |expr| Constrain.do_constrain_value?(value, expr) } or
68
64
  raise MatchError.new(value, exprs, message: message, unwind: unwind)
69
65
  end
70
- !not_argument || value != not_value or
71
- raise MatchError.new(
72
- value, exprs, message: message, unwind: unwind, not_argument: true, not_value: not_value)
73
-
74
66
  rescue ArgumentError, Constrain::MatchError => ex
75
67
  ex.set_backtrace(caller[1 + unwind..-1])
76
68
  raise
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: constrain
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-21 00:00:00.000000000 Z
11
+ date: 2023-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simplecov