lab42_basic_constraints 0.1.2 → 0.2.1
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 +45 -25
- data/lib/lab42/basic_constraints.rb +21 -18
- data/lib/lab42/basic_constraints/constraint.rb +16 -6
- data/lib/lab42/basic_constraints/constraints/int.rb +19 -0
- data/lib/lab42/basic_constraints/helpers/range_helper.rb +29 -0
- data/lib/lab42/basic_constraints/implementation.rb +85 -7
- data/lib/lab42/basic_constraints/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9805a493dac3acaa452c4a1a22888e78c3f8b63e1b1624e2ce5fa8604db92706
|
4
|
+
data.tar.gz: f76c354a6dce71e35e76a9ba4e5edcd3a11e77206f8a2c199be1f0ea8e0d8667
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e07c41ee4c38e521e6312dac59873b2a27127292a3c59bb554df3c3e2724c1209b96fcd9c4153fbe6dc11e752c1965acb45a6c8db2d0b17b50cd89af6a9be9e
|
7
|
+
data.tar.gz: 889fa0aba02c77788aa583275c1daf83802d9277abcf7d47955cf73020266702f2da9e8e807e83f29cb3182dce3982b72a69d3edf06d911a0b4c33262846fbd2
|
data/README.md
CHANGED
@@ -17,27 +17,46 @@ Given That we alias `Lab42::BasicConstraints` to `BC`
|
|
17
17
|
require "lab42/basic_constraints/alias"
|
18
18
|
```
|
19
19
|
|
20
|
+
Given
|
21
|
+
```ruby
|
22
|
+
let :all_basic_constraints do
|
23
|
+
%i[
|
24
|
+
all_digits_string alphanumeric_string
|
25
|
+
bool
|
26
|
+
date date_time day
|
27
|
+
hour
|
28
|
+
int
|
29
|
+
lowercase_string
|
30
|
+
minute month
|
31
|
+
non_negative_int non_negative_number number
|
32
|
+
positive_int positive_number
|
33
|
+
second string symbol
|
34
|
+
uppercase_string
|
35
|
+
year
|
36
|
+
]
|
37
|
+
end
|
38
|
+
let :all_parametrized_constraints do
|
39
|
+
%i[ int_range limited_string ]
|
40
|
+
end
|
41
|
+
|
42
|
+
```
|
20
43
|
Then All Basic Constraints can be listed by means of `BC.all_constraints`
|
21
44
|
|
22
45
|
```ruby
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
uppercase_string
|
35
|
-
year
|
36
|
-
]
|
37
|
-
|
38
|
-
expect( BC.all_constraints ).to eq(all_basic_constraints)
|
46
|
+
|
47
|
+
expect( Set.new(BC.all_constraints) ).to eq(Set.new(all_basic_constraints + all_parametrized_constraints))
|
48
|
+
```
|
49
|
+
|
50
|
+
And they are implemented of course
|
51
|
+
```ruby
|
52
|
+
all_basic_constraints.each do | constraint_name |
|
53
|
+
expect( BC.from_symbol(constraint_name) ).to be_a(BC::Constraint)
|
54
|
+
end
|
55
|
+
expect( BC.int_range(min: 0) ).to be_a(BC::Constraint)
|
56
|
+
expect( BC.limited_string(max: 10) ).to be_a(BC::Constraint)
|
39
57
|
```
|
40
58
|
|
59
|
+
|
41
60
|
## So we got the ball, now use it!
|
42
61
|
|
43
62
|
The ball, BTW, is a `Lab42::Result` see [lab42_result gem](https://rubygems.org/gems/lab42_result/) for more info
|
@@ -74,17 +93,12 @@ Example: Constraints with and without defaults
|
|
74
93
|
|
75
94
|
```
|
76
95
|
|
77
|
-
|
78
|
-
[here](speculations/constraints.md)
|
79
|
-
|
80
|
-
## Context We are still in Beta and therefor
|
81
|
-
|
82
|
-
Example: Some constraints are not yet implemented
|
83
|
-
|
96
|
+
Example: Avoiding the Exception, à la `Hash#fetch`
|
84
97
|
```ruby
|
85
|
-
expect
|
98
|
+
expect( BC.from_symbol(:positive_number).default{42} ).to eq(42)
|
86
99
|
```
|
87
100
|
|
101
|
+
|
88
102
|
## Context Time's a Sticky Wicket
|
89
103
|
|
90
104
|
... but as defaults are defined for runtime that shall really help us with that
|
@@ -112,7 +126,7 @@ Example: Illegal Dates
|
|
112
126
|
```ruby
|
113
127
|
d.("2020-00-01") in [raised, message ]
|
114
128
|
expect( raised ).to eq(error)
|
115
|
-
expect( message ).to eq("2020-00-01 is not a legal date
|
129
|
+
expect( message ).to eq(%{"2020-00-01" is not a legal date})
|
116
130
|
```
|
117
131
|
|
118
132
|
## Context Equality More Of A Tricky Sticker
|
@@ -139,6 +153,12 @@ Then we can compare as follows
|
|
139
153
|
expect( def42.default ).to eq(42)
|
140
154
|
```
|
141
155
|
|
156
|
+
## Detailed Description of all Constraints
|
157
|
+
|
158
|
+
[date_and_time_constraints](date_and_time_constraints.md )
|
159
|
+
[div_constraints](div_constraints.md )
|
160
|
+
[string_constraints](string_constraints.md )
|
161
|
+
|
142
162
|
# LICENSE
|
143
163
|
|
144
164
|
Copyright 2020 Robert Dober robert.dober@gmail.com
|
@@ -2,37 +2,38 @@ require_relative "basic_constraints/implementation.rb"
|
|
2
2
|
module Lab42
|
3
3
|
module BasicConstraints extend self
|
4
4
|
Constraints = {
|
5
|
-
all_digits_string: :
|
6
|
-
alphanumeric_string: :
|
5
|
+
all_digits_string: :all_digits_string,
|
6
|
+
alphanumeric_string: :alphanumeric_string,
|
7
7
|
|
8
8
|
bool: ->(x){[false, true].include? x},
|
9
9
|
|
10
10
|
date: :date,
|
11
|
-
date_time: :
|
12
|
-
day: :
|
11
|
+
date_time: :date_time,
|
12
|
+
day: :day,
|
13
13
|
|
14
|
-
hour: :
|
14
|
+
hour: :hour,
|
15
15
|
|
16
|
-
|
16
|
+
int: Integer,
|
17
|
+
int_range: :int_range,
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
limited_string: :limited_string,
|
20
|
+
lowercase_string: :lowercase_string,
|
21
|
+
|
22
|
+
minute: :minute,
|
23
|
+
month: :month,
|
20
24
|
|
21
|
-
non_empty_string: :not_yet_implemented,
|
22
|
-
non_negative_float: :not_yet_implemented,
|
23
25
|
non_negative_int: :non_negative_int,
|
26
|
+
non_negative_number: :non_negative_number,
|
27
|
+
number: Numeric,
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
positive_float: :not_yet_implemented,
|
28
|
-
positive_int: :not_yet_implemented,
|
29
|
+
positive_int: :positive_int,
|
29
30
|
positive_number: :positive_number,
|
30
31
|
|
31
|
-
second: :
|
32
|
-
|
33
|
-
|
32
|
+
second: :second,
|
33
|
+
string: String,
|
34
|
+
symbol: Symbol,
|
34
35
|
|
35
|
-
uppercase_string: :
|
36
|
+
uppercase_string: :uppercase_string,
|
36
37
|
|
37
38
|
year: :year
|
38
39
|
}
|
@@ -49,6 +50,8 @@ module Lab42
|
|
49
50
|
Constraint.new(name, &cons)
|
50
51
|
when Symbol
|
51
52
|
Implementation.send(cons, *args, **kwds)
|
53
|
+
when Class
|
54
|
+
Constraint.new(name){ cons === _1 }
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
@@ -12,12 +12,17 @@ module Lab42
|
|
12
12
|
Result.error("#{_show value} is not a legal #{@name}", error: Lab42::BasicConstraints::ConstraintError)
|
13
13
|
end
|
14
14
|
|
15
|
-
def default
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def default &blk
|
16
|
+
if @has_default
|
17
|
+
case @default
|
18
|
+
when Proc
|
19
|
+
@default.()
|
20
|
+
else
|
21
|
+
@default
|
22
|
+
end
|
19
23
|
else
|
20
|
-
|
24
|
+
return blk.() if blk
|
25
|
+
raise Lab42::BasicConstraints::MissingDefaultError, "Constraint #{name} has no predefined default"
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
@@ -28,6 +33,7 @@ module Lab42
|
|
28
33
|
else
|
29
34
|
blk
|
30
35
|
end
|
36
|
+
@has_default = true
|
31
37
|
self
|
32
38
|
end
|
33
39
|
|
@@ -36,6 +42,8 @@ module Lab42
|
|
36
42
|
case value
|
37
43
|
when NilClass
|
38
44
|
"nil"
|
45
|
+
when String
|
46
|
+
value.inspect
|
39
47
|
else
|
40
48
|
value
|
41
49
|
end
|
@@ -43,9 +51,11 @@ module Lab42
|
|
43
51
|
|
44
52
|
def initialize name, &blk
|
45
53
|
@constraint = blk
|
46
|
-
@
|
54
|
+
@has_default = false
|
55
|
+
@default = -> {}
|
47
56
|
@name = name
|
48
57
|
end
|
49
58
|
end
|
50
59
|
end
|
51
60
|
end
|
61
|
+
require_relative "constraints/int"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "../helpers/range_helper.rb"
|
2
|
+
module Lab42
|
3
|
+
module BasicConstraints
|
4
|
+
class Constraint
|
5
|
+
class IntConstraint < Constraint
|
6
|
+
|
7
|
+
private
|
8
|
+
def initialize name, range: nil, min: nil, max: nil
|
9
|
+
super(name)
|
10
|
+
range = Helpers::RangeHelper.make_range!(range: range, min: min, max: max)
|
11
|
+
@constraint = -> (value) {
|
12
|
+
Integer === value && range === value
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Lab42
|
2
|
+
module BasicConstraints
|
3
|
+
module Helpers
|
4
|
+
module RangeHelper extend self
|
5
|
+
|
6
|
+
def make_range(range: nil, min: nil, max: nil)
|
7
|
+
return unless range || min || max
|
8
|
+
raise ArgumentError, "cannot provide min or max with range" if
|
9
|
+
range && (min || max)
|
10
|
+
range || _make_min_max_range(min, max)
|
11
|
+
end
|
12
|
+
|
13
|
+
def make_range!(range: nil, min: nil, max: nil)
|
14
|
+
make_range(range: range, min: min, max: max)
|
15
|
+
.tap do |range|
|
16
|
+
raise ArgumentError, "Must provide either range or min or max" unless range
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def _make_min_max_range(min, max)
|
22
|
+
min ||= 0
|
23
|
+
max ||= Float::INFINITY
|
24
|
+
min..max
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,9 +1,38 @@
|
|
1
1
|
require_relative "constraint"
|
2
|
+
require_relative "helpers/range_helper"
|
2
3
|
module Lab42
|
3
4
|
module BasicConstraints
|
4
5
|
|
5
6
|
module Implementation extend self
|
6
7
|
|
8
|
+
IntConstraints = {
|
9
|
+
day: 1..31,
|
10
|
+
hour: 0..23,
|
11
|
+
minute: 0..59,
|
12
|
+
month: 1..12,
|
13
|
+
second: 0..59
|
14
|
+
}
|
15
|
+
IntConstraints.each do |constraint_name, constraint_range|
|
16
|
+
define_method constraint_name do
|
17
|
+
Constraint::IntConstraint.new(constraint_name, range: constraint_range)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def int_range(range: nil, min: nil, max: nil)
|
22
|
+
Constraint::IntConstraint.new(:int_range, range: range, min: min, max: max)
|
23
|
+
end
|
24
|
+
|
25
|
+
StringConstraints = {
|
26
|
+
all_digits_string: %r{\A\d*\z},
|
27
|
+
alphanumeric_string: %r{\A[[:alnum:]]*\z}
|
28
|
+
}
|
29
|
+
|
30
|
+
StringConstraints.each do |constraint_name, constraint_rgx|
|
31
|
+
define_method constraint_name do |size: nil, min: nil, max: nil|
|
32
|
+
_regex_constraint(constraint_name, constraint_rgx, size: size, min: min, max: max)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
7
36
|
def date default: nil
|
8
37
|
require "date"
|
9
38
|
Constraint.new(:date) do |value|
|
@@ -14,22 +43,55 @@ module Lab42
|
|
14
43
|
end
|
15
44
|
end
|
16
45
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
46
|
+
def date_time default: nil
|
47
|
+
require "date"
|
48
|
+
Constraint.new(:date_time) do |value|
|
49
|
+
DateTime.parse(value) rescue false
|
20
50
|
end
|
51
|
+
.set_default default do
|
52
|
+
DateTime.now.iso8601
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def limited_string size: nil, min: nil, max: nil
|
57
|
+
size_range = Helpers::RangeHelper.make_range!(range: size, min: min, max: max)
|
58
|
+
Constraint.new(:limited_string) do |value|
|
59
|
+
String === value && size_range === value.size
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def lowercase_string
|
64
|
+
Constraint.new :lowercase_string do |value|
|
65
|
+
String === value && value.downcase == value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def non_negative_int
|
70
|
+
Constraint::IntConstraint.new(:non_negative_int, min: 0)
|
21
71
|
.set_default(0)
|
22
72
|
end
|
23
73
|
|
74
|
+
def non_negative_number
|
75
|
+
Constraint.new :non_negative_number do |value|
|
76
|
+
Numeric === value && !(Complex === value) && value >= 0
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def positive_int
|
81
|
+
Constraint::IntConstraint.new(:positive_int, min: 1)
|
82
|
+
.set_default(1)
|
83
|
+
end
|
84
|
+
|
24
85
|
def positive_number
|
25
86
|
Constraint.new :positive_number do |value|
|
26
|
-
|
27
|
-
Float === value && value > 0.0
|
87
|
+
Numeric === value && value > 0
|
28
88
|
end
|
29
89
|
end
|
30
90
|
|
31
|
-
def
|
32
|
-
|
91
|
+
def uppercase_string
|
92
|
+
Constraint.new :uppercase_string do |value|
|
93
|
+
String === value && value.upcase == value
|
94
|
+
end
|
33
95
|
end
|
34
96
|
|
35
97
|
def year
|
@@ -40,6 +102,22 @@ module Lab42
|
|
40
102
|
Time.now.utc.year
|
41
103
|
end
|
42
104
|
end
|
105
|
+
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def _regex_constraint(name, rgx, size: nil, min: nil, max: nil)
|
110
|
+
range_size = Helpers::RangeHelper.make_range(range: size, min: min, max: max)
|
111
|
+
if range_size
|
112
|
+
Constraint.new(name) do |value|
|
113
|
+
String === value && range_size === value.size && rgx === value
|
114
|
+
end
|
115
|
+
else
|
116
|
+
Constraint.new(name) do |value|
|
117
|
+
String === value && rgx === value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
43
121
|
end
|
44
122
|
end
|
45
123
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab42_basic_constraints
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lab42_result
|
@@ -91,6 +91,8 @@ files:
|
|
91
91
|
- lib/lab42/basic_constraints.rb
|
92
92
|
- lib/lab42/basic_constraints/alias.rb
|
93
93
|
- lib/lab42/basic_constraints/constraint.rb
|
94
|
+
- lib/lab42/basic_constraints/constraints/int.rb
|
95
|
+
- lib/lab42/basic_constraints/helpers/range_helper.rb
|
94
96
|
- lib/lab42/basic_constraints/implementation.rb
|
95
97
|
- lib/lab42/basic_constraints/version.rb
|
96
98
|
homepage: https://bitbucket.org/robertdober/lab42_basic_constraints
|
@@ -112,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
114
|
- !ruby/object:Gem::Version
|
113
115
|
version: '0'
|
114
116
|
requirements: []
|
115
|
-
rubygems_version: 3.1.
|
117
|
+
rubygems_version: 3.1.2
|
116
118
|
signing_key:
|
117
119
|
specification_version: 4
|
118
120
|
summary: Basic, useful and recurring constraints
|