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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1670a94a94e7a862d42f660df6b15c38efd8aada76025516353d73c8f146a48
4
- data.tar.gz: e7620b5d6b2ae1813d17cff3cce12fa6a935728f24d612d2a36451bc526dfcf2
3
+ metadata.gz: 9805a493dac3acaa452c4a1a22888e78c3f8b63e1b1624e2ce5fa8604db92706
4
+ data.tar.gz: f76c354a6dce71e35e76a9ba4e5edcd3a11e77206f8a2c199be1f0ea8e0d8667
5
5
  SHA512:
6
- metadata.gz: 5416abb445fd45109ad28acc167c842d801467119469fcf4d1ffc81de578daab6cdfc5c361e018079bc23bfaa762860289cb09516b267c8621bee1262c398657
7
- data.tar.gz: '0148614a24de35f98bc4f997dae7388492f386e1ab980f90e4835ea94ae3c7da00c8741f3063e6028575e430b34deccb9dba89a6debec79feeff87c3bc77b9a0'
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
- all_basic_constraints = %i[
24
- all_digits_string alphanumeric_string
25
- bool
26
- date date_time day
27
- hour
28
- lowercase_string
29
- minute month
30
- non_empty_string non_negative_float non_negative_int non_negative_number
31
- positive_float positive_int positive_number
32
- second
33
- time
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
- A detailed description of all constraints can be found
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{ BC.all_digits_string }.to raise_error(NotImplementedError)
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: :not_yet_implemented,
6
- alphanumeric_string: :not_yet_implemented,
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: :not_yet_implemented,
12
- day: :not_yet_implemented,
11
+ date_time: :date_time,
12
+ day: :day,
13
13
 
14
- hour: :not_yet_implemented,
14
+ hour: :hour,
15
15
 
16
- lowercase_string: :not_yet_implemented,
16
+ int: Integer,
17
+ int_range: :int_range,
17
18
 
18
- minute: :not_yet_implemented,
19
- month: :not_yet_implemented,
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
- non_negative_number: :not_yet_implemented,
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: :not_yet_implemented,
32
-
33
- time: :not_yet_implemented,
32
+ second: :second,
33
+ string: String,
34
+ symbol: Symbol,
34
35
 
35
- uppercase_string: :not_yet_implemented,
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
- case @default
17
- when Proc
18
- @default.()
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
- @default
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
- @default = -> {raise Lab42::BasicConstraints::MissingDefaultError, "Constraint #{name} has no predefined default"}
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 non_negative_int
18
- Constraint.new :non_negative_int do |value|
19
- Integer === value && value >= 0
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
- Integer === value && value > 0 ||
27
- Float === value && value > 0.0
87
+ Numeric === value && value > 0
28
88
  end
29
89
  end
30
90
 
31
- def not_yet_implemented
32
- raise NotImplementedError
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
@@ -1,5 +1,5 @@
1
1
  module Lab42
2
2
  module BasicConstraints
3
- VERSION = "0.1.2"
3
+ VERSION = "0.2.1"
4
4
  end
5
5
  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.2
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-20 00:00:00.000000000 Z
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.4
117
+ rubygems_version: 3.1.2
116
118
  signing_key:
117
119
  specification_version: 4
118
120
  summary: Basic, useful and recurring constraints