domainic-type 0.1.0.alpha.3.2.0 → 0.1.0.alpha.3.4.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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/README.md +66 -10
  4. data/docs/USAGE.md +787 -0
  5. data/lib/domainic/type/accessors.rb +3 -2
  6. data/lib/domainic/type/behavior/date_time_behavior.rb +121 -37
  7. data/lib/domainic/type/behavior.rb +16 -0
  8. data/lib/domainic/type/config/registry.yml +24 -0
  9. data/lib/domainic/type/constraint/constraints/nor_constraint.rb +1 -1
  10. data/lib/domainic/type/constraint/constraints/predicate_constraint.rb +76 -0
  11. data/lib/domainic/type/definitions.rb +212 -0
  12. data/lib/domainic/type/types/core/complex_type.rb +122 -0
  13. data/lib/domainic/type/types/core/range_type.rb +47 -0
  14. data/lib/domainic/type/types/core/rational_type.rb +38 -0
  15. data/lib/domainic/type/types/core_extended/big_decimal_type.rb +34 -0
  16. data/lib/domainic/type/types/core_extended/set_type.rb +34 -0
  17. data/lib/domainic/type/types/datetime/date_time_string_type.rb +156 -0
  18. data/lib/domainic/type/types/datetime/timestamp_type.rb +50 -0
  19. data/sig/domainic/type/accessors.rbs +2 -2
  20. data/sig/domainic/type/behavior/date_time_behavior.rbs +35 -23
  21. data/sig/domainic/type/behavior.rbs +9 -0
  22. data/sig/domainic/type/constraint/constraints/predicate_constraint.rbs +56 -0
  23. data/sig/domainic/type/definitions.rbs +165 -0
  24. data/sig/domainic/type/types/core/complex_type.rbs +96 -0
  25. data/sig/domainic/type/types/core/range_type.rbs +41 -0
  26. data/sig/domainic/type/types/core/rational_type.rbs +32 -0
  27. data/sig/domainic/type/types/core_extended/big_decimal_type.rbs +27 -0
  28. data/sig/domainic/type/types/core_extended/set_type.rbs +27 -0
  29. data/sig/domainic/type/types/datetime/date_time_string_type.rbs +124 -0
  30. data/sig/domainic/type/types/datetime/timestamp_type.rbs +44 -0
  31. metadata +25 -6
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/date_time_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating Unix timestamps (seconds since the Unix epoch).
9
+ #
10
+ # This type ensures the value is an `Integer` representing a valid Unix
11
+ # timestamp. It integrates with `DateTimeBehavior` to provide a rich set of
12
+ # validation capabilities, including chronological constraints and range checks.
13
+ #
14
+ # Key features:
15
+ # - Ensures the value is an `Integer` representing a Unix timestamp.
16
+ # - Supports chronological relationship constraints (e.g., before, after).
17
+ # - Provides range, equality, and nilable checks.
18
+ #
19
+ # @example Basic usage
20
+ # type = TimestampType.new
21
+ # type.validate(Time.now.to_i) # => true
22
+ # type.validate(Date.today.to_time.to_i) # => true
23
+ # type.validate('invalid') # => false
24
+ #
25
+ # @example Range validation
26
+ # type = TimestampType.new
27
+ # .being_between(Time.now.to_i, (Time.now + 3600).to_i)
28
+ # type.validate((Time.now + 1800).to_i) # => true
29
+ # type.validate((Time.now + 7200).to_i) # => false
30
+ #
31
+ # @example Historical timestamps
32
+ # type = TimestampType.new
33
+ # type.validate(-1234567890) # => true (date before 1970-01-01)
34
+ #
35
+ # @example Nilable timestamp
36
+ # nilable_type = _Nilable(TimestampType.new)
37
+ # nilable_type.validate(nil) # => true
38
+ #
39
+ # @author {https://aaronmallen.me Aaron Allen}
40
+ # @since 0.1.0
41
+ class TimestampType
42
+ # @rbs! extend Behavior::ClassMethods
43
+
44
+ include Behavior
45
+ include Behavior::DateTimeBehavior
46
+
47
+ intrinsically_constrain :self, :type, Integer, abort_on_failure: true, description: :not_described
48
+ end
49
+ end
50
+ end
@@ -1,11 +1,11 @@
1
1
  module Domainic
2
2
  module Type
3
- type accessor = :abs | :begin | :chars | :class | :count | :end | :entries | :first | :keys | :last | :length | :self | :size | :values
3
+ type accessor = :abs | :begin | :chars | :class | :count | :end | :entries | :first | :keys | :last | :length | :real | :self | :size | :values
4
4
 
5
5
  # A list of valid access methods that can be used to retrieve values for constraint validation.
6
6
  # These methods represent common Ruby interfaces for accessing collection sizes, ranges, and values.
7
7
  #
8
- # - :abs - For absolute values
8
+ # - :abs, :real - For absolute values
9
9
  # - :begin, :end - For Range-like objects
10
10
  # - :class - For type checking
11
11
  # - :count, :length, :size - For measuring collections
@@ -24,73 +24,85 @@ module Domainic
24
24
  # @author {https://aaronmallen.me Aaron Allen}
25
25
  # @since 0.1.0
26
26
  module DateTimeBehavior
27
- TO_DATETIME_COERCER: Proc
27
+ # The supported date/time patterns for parsing date/time strings
28
+ #
29
+ # @note This list is ordered from most specific to least specific to ensure that the most specific patterns are
30
+ # tried first. This is important because some patterns are more lenient than others and may match a wider range
31
+ # of input strings.
32
+ #
33
+ # @return [Array<String>] the supported date/time patterns
34
+ DATETIME_PATTERNS: Array[String]
35
+
36
+ # Coerce a value to a Date, DateTime, or Time object
37
+ #
38
+ # @return [Proc] a lambda that coerces a value to a Date, DateTime, or Time object
39
+ TO_DATETIME_COERCER: ^(Date | DateTime | Integer | String | Time value) -> (Date | DateTime | Time)
28
40
 
29
41
  # Parse arguments for being_between
30
42
  #
31
43
  # @note this in my opinion is better than polluting the namespace of the including class even with a private
32
44
  # method. This way, the method is only available within the module itself. See {#being_between}.
33
45
  #
34
- # @param after [Date, DateTime, String, Time, nil] minimum size value from positional args
35
- # @param before [Date, DateTime, String, Time, nil] maximum size value from positional args
46
+ # @param after [Date, DateTime, Integer, String, Time, nil] minimum size value from positional args
47
+ # @param before [Date, DateTime, Integer, String, Time, nil] maximum size value from positional args
36
48
  # @param options [Hash] keyword arguments containing after/before values
37
49
  #
38
50
  # @raise [ArgumentError] if minimum or maximum value can't be determined
39
- # @return [Array<Date, DateTime, String, Time, nil>] parsed [after, before] values
40
- private def self.parse_being_between_arguments!: ((Date | DateTime | String | Time)? after, (Date | DateTime | String | Time)? before, Hash[Symbol, (Date | DateTime | String | Time)?] options) -> Array[(Date | DateTime | String | Time)?]
51
+ # @return [Array<Date, DateTime, Integer, String, Time, nil>] parsed [after, before] values
52
+ private def self.parse_being_between_arguments!: ((Date | DateTime | Integer | String | Time)? after, (Date | DateTime | Integer | String | Time)? before, Hash[Symbol, (Date | DateTime | Integer | String | Time)?] options) -> Array[(Date | DateTime | Integer | String | Time)?]
41
53
 
42
54
  # Raise appropriate ArgumentError for being_between
43
55
  #
44
56
  # @param original_caller [Array<String>] caller stack for error
45
- # @param after [Date, DateTime, String, Time, nil] after value from positional args
46
- # @param before [Date, DateTime, String, Time, nil] before value from positional args
57
+ # @param after [Date, DateTime, Integer, String, Time, nil] after value from positional args
58
+ # @param before [Date, DateTime, Integer, String, Time, nil] before value from positional args
47
59
  # @param options [Hash] keyword arguments containing after/before values
48
60
  #
49
61
  # @raise [ArgumentError] with appropriate message
50
62
  # @return [void]
51
- private def self.raise_being_between_argument_error!: (Array[String] original_caller, (Date | DateTime | String | Time)? after, (Date | DateTime | String | Time)? before, Hash[Symbol, (Date | DateTime | String | Time)?] options) -> void
63
+ private def self.raise_being_between_argument_error!: (Array[String] original_caller, (Date | DateTime | Integer | String | Time)? after, (Date | DateTime | Integer | String | Time)? before, Hash[Symbol, (Date | DateTime | Integer | String | Time)?] options) -> void
52
64
 
53
65
  # Constrain the value to be chronologically after a given date/time
54
66
  #
55
- # @param other [Date, DateTime, String, Time] the date/time to compare against
67
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
56
68
  # @return [self] self for method chaining
57
- def being_after: (Date | DateTime | String | Time other) -> Behavior
69
+ def being_after: (Date | DateTime | Integer | String | Time other) -> Behavior
58
70
 
59
71
  alias after being_after
60
72
 
61
73
  # Constrain the value to be chronologically before a given date/time
62
74
  #
63
- # @param other [Date, DateTime, String, Time] the date/time to compare against
75
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
64
76
  # @return [self] self for method chaining
65
- def being_before: (Date | DateTime | String | Time other) -> Behavior
77
+ def being_before: (Date | DateTime | Integer | String | Time other) -> Behavior
66
78
 
67
79
  alias before being_before
68
80
 
69
81
  # Constrain the value to be chronologically between two date/times
70
82
  #
71
- # @param after [Date, DateTime, String, Time] the earliest allowed date/time
72
- # @param before [Date, DateTime, String, Time] the latest allowed date/time
83
+ # @param after [Date, DateTime, Integer, String, Time] the earliest allowed date/time
84
+ # @param before [Date, DateTime, Integer, String, Time] the latest allowed date/time
73
85
  # @param options [Hash] alternative way to specify after/before via keywords
74
- # @option options [Date, DateTime, String, Time] :after earliest allowed date/time
75
- # @option options [Date, DateTime, String, Time] :before latest allowed date/time
86
+ # @option options [Date, DateTime, Integer, String, Time] :after earliest allowed date/time
87
+ # @option options [Date, DateTime, Integer, String, Time] :before latest allowed date/time
76
88
  # @return [self] self for method chaining
77
- def being_between: (Date | DateTime | String | Time after, Date | DateTime | String | Time before) -> Behavior
89
+ def being_between: (Date | DateTime | Integer | String | Time after, Date | DateTime | Integer | String | Time before) -> Behavior
78
90
 
79
91
  alias between being_between
80
92
 
81
93
  # Constrain the value to be exactly equal to a given date/time
82
94
  #
83
- # @param other [Date, DateTime, String, Time] the date/time to compare against
95
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
84
96
  # @return [self] self for method chaining
85
- def being_equal_to: (Date | DateTime | String | Time other) -> Behavior
97
+ def being_equal_to: (Date | DateTime | Integer | String | Time other) -> Behavior
86
98
 
87
99
  alias at being_equal_to
88
100
 
89
101
  # Constrain the value to be chronologically on or after a given date/time
90
102
  #
91
- # @param other [Date, DateTime, String, Time] the date/time to compare against
103
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
92
104
  # @return [self] self for method chaining
93
- def being_on_or_after: (Date | DateTime | String | Time other) -> Behavior
105
+ def being_on_or_after: (Date | DateTime | Integer | String | Time other) -> Behavior
94
106
 
95
107
  alias at_or_after being_on_or_after
96
108
 
@@ -100,9 +112,9 @@ module Domainic
100
112
 
101
113
  # Constrain the value to be chronologically on or before a given date/time
102
114
  #
103
- # @param other [Date, DateTime, String, Time] the date/time to compare against
115
+ # @param other [Date, DateTime, Integer, String, Time] the date/time to compare against
104
116
  # @return [self] self for method chaining
105
- def being_on_or_before: (Date | DateTime | String | Time other) -> Behavior
117
+ def being_on_or_before: (Date | DateTime | Integer | String | Time other) -> Behavior
106
118
 
107
119
  alias at_or_before being_on_or_before
108
120
 
@@ -125,6 +125,15 @@ module Domainic
125
125
  # @return [void]
126
126
  def initialize: (**untyped) -> void
127
127
 
128
+ # Add a custom constraint to this type.
129
+ #
130
+ # @param proc [Proc] the constraint to add
131
+ # @param accessor [Type::Accessor] the accessor to constrain
132
+ # @param options [Hash{Symbol => Object}] additional constraint options
133
+ #
134
+ # @return [self] for chaining constraints
135
+ def satisfies: (Proc proc, ?accessor: Type::accessor, **untyped options) -> Behavior
136
+
128
137
  # Convert the type to a String representation.
129
138
  #
130
139
  # @return [String] The type as a String
@@ -0,0 +1,56 @@
1
+ module Domainic
2
+ module Type
3
+ module Constraint
4
+ # A constraint for validating values using a custom predicate function.
5
+ #
6
+ # This constraint allows for custom validation logic through a Proc that returns
7
+ # a boolean value. It enables users to create arbitrary validation rules when
8
+ # the built-in constraints don't cover their specific needs.
9
+ #
10
+ # @example Basic usage
11
+ # constraint = PredicateConstraint.new(:self, ->(x) { x > 0 })
12
+ # constraint.satisfied?(1) # => true
13
+ # constraint.satisfied?(-1) # => false
14
+ #
15
+ # @example With custom violation description
16
+ # constraint = PredicateConstraint.new(:self, ->(x) { x > 0 }, violation_description: 'not greater than zero')
17
+ # constraint.satisfied?(-1) # => false
18
+ # constraint.short_violation_description # => "not greater than zero"
19
+ #
20
+ # @author {https://aaronmallen.me Aaron Allen}
21
+ # @since 0.1.0
22
+ class PredicateConstraint
23
+ type expected = ^(untyped value) -> bool
24
+
25
+ type options = { ?violation_description: String }
26
+
27
+ include Behavior[expected, untyped, options]
28
+
29
+ # Get a description of what the constraint expects.
30
+ #
31
+ # @note This constraint type does not provide a description as predicates are arbitrary.
32
+ #
33
+ # @return [String] an empty string
34
+ def short_description: ...
35
+
36
+ # Get a description of why the predicate validation failed.
37
+ #
38
+ # @return [String] the custom violation description if provided
39
+ def short_violation_description: ...
40
+
41
+ # Check if the value satisfies the predicate function.
42
+ #
43
+ # @return [Boolean] true if the predicate returns true
44
+ def satisfies_constraint?: ...
45
+
46
+ # Validate that the expectation is a Proc.
47
+ #
48
+ # @param expectation [Object] the expectation to validate
49
+ #
50
+ # @raise [ArgumentError] if the expectation is not a Proc
51
+ # @return [void]
52
+ def validate_expectation!: ...
53
+ end
54
+ end
55
+ end
56
+ end
@@ -64,6 +64,29 @@ module Domainic
64
64
 
65
65
  alias _List? _Array?
66
66
 
67
+ # Creates a BigDecimalType instance.
68
+ #
69
+ # @example
70
+ # type = _BigDecimal
71
+ # type.validate(BigDecimal('123.45')) # => true
72
+ #
73
+ # @param options [Hash] additional configuration options
74
+ #
75
+ # @return [Domainic::Type::BigDecimalType] the created type
76
+ def _BigDecimal: (**__todo__ options) -> BigDecimalType
77
+
78
+ # Creates a nilable BigDecimalType instance.
79
+ #
80
+ # @example
81
+ # type = _BigDecimal?
82
+ # type.validate(BigDecimal('123.45')) # => true
83
+ # type.validate(nil) # => true
84
+ #
85
+ # @param options [Hash] additional configuration options
86
+ #
87
+ # @return [Domainic::Type::UnionType] the created type (BigDecimal or NilClass)
88
+ def _BigDecimal?: (**__todo__ options) -> UnionType
89
+
67
90
  # Creates a Boolean type.
68
91
  #
69
92
  # Represents a union of TrueClass and FalseClass.
@@ -111,6 +134,28 @@ module Domainic
111
134
 
112
135
  alias _Cuid? _CUID?
113
136
 
137
+ # Creates a ComplexType instance.
138
+ #
139
+ # @example
140
+ # type = _Complex
141
+ # type.validate(Complex(1, 2)) # => true
142
+ #
143
+ # @param options [Hash] additional configuration options
144
+ #
145
+ # @return [Domainic::Type::ComplexType] the created type
146
+ def _Complex: (**__todo__ options) -> ComplexType
147
+
148
+ # Creates a nilable ComplexType instance.
149
+ #
150
+ # @example
151
+ # type = _Complex?
152
+ # type.validate(Complex(1, 2)) # => true
153
+ #
154
+ # @param options [Hash] additional configuration options
155
+ #
156
+ # @return [Domainic::Type::UnionType] the created type (Complex or NilClass)
157
+ def _Complex?: (**__todo__ options) -> UnionType
158
+
114
159
  # Creates a DateType instance.
115
160
  #
116
161
  # DateType restricts values to valid `Date` objects.
@@ -159,6 +204,34 @@ module Domainic
159
204
  # @return [Domainic::Type::UnionType] the created type (DateTimeType or NilClass)
160
205
  def _DateTime?: (**__todo__ options) -> UnionType
161
206
 
207
+ # Creates a DateTimeStringType instance.
208
+ #
209
+ # DateTimeStringType restricts values to valid date-time strings.
210
+ #
211
+ # @example
212
+ # type = _DateTimeString
213
+ # type.validate('2024-01-01T12:00:00Z') # => true
214
+ #
215
+ # @param options [Hash] additional configuration options
216
+ #
217
+ # @return [Domainic::Type::DateTimeStringType] the created type
218
+ def _DateTimeString: (**__todo__ options) -> DateTimeStringType
219
+
220
+ alias _DateString _DateTimeString
221
+
222
+ # Creates a nilable DateTimeStringType instance.
223
+ #
224
+ # @example
225
+ # _DateTimeString? === '2024-01-01T12:00:00Z' # => true
226
+ # _DateTimeString? === nil # => true
227
+ #
228
+ # @param options [Hash] additional configuration options
229
+ #
230
+ # @return [Domainic::Type::UnionType] the created type (DateTimeStringType or NilClass)
231
+ def _DateTimeString?: (**__todo__ options) -> UnionType
232
+
233
+ alias _DateString? _DateTimeString?
234
+
162
235
  # Creates a DuckType instance.
163
236
  #
164
237
  # DuckType allows specifying behavior based on method availability.
@@ -395,6 +468,74 @@ module Domainic
395
468
 
396
469
  alias _Nullable _Nilable
397
470
 
471
+ # Creates a RangeType instance.
472
+ #
473
+ # @example
474
+ # type = _Range
475
+ # type.validate(1..10) # => true
476
+ #
477
+ # @param options [Hash] additional configuration options
478
+ #
479
+ # @return [Domainic::Type::RangeType] the created type
480
+ def _Range: (**__todo__ options) -> RangeType
481
+
482
+ # Creates a nilable RangeType instance.
483
+ #
484
+ # @example
485
+ # type = _Range?
486
+ # type.validate(1..10) # => true
487
+ #
488
+ # @param options [Hash] additional configuration options
489
+ #
490
+ # @return [Domainic::Type::UnionType] the created type (Range or NilClass)
491
+ def _Range?: (**__todo__ options) -> UnionType
492
+
493
+ # Creates a RationalType instance.
494
+ #
495
+ # @example
496
+ # type = _Rational
497
+ # type.validate(Rational(1, 2)) # => true
498
+ #
499
+ # @param options [Hash] additional configuration options
500
+ #
501
+ # @return [Domainic::Type::RationalType] the created type
502
+ def _Rational: (**__todo__ options) -> RationalType
503
+
504
+ # Creates a nilable RationalType instance.
505
+ #
506
+ # @example
507
+ # type = _Rational?
508
+ # type.validate(Rational(1, 2)) # => true
509
+ # type.validate(nil) # => true
510
+ #
511
+ # @param options [Hash] additional configuration options
512
+ #
513
+ # @return [Domainic::Type::UnionType] the created type (Rational or NilClass)
514
+ def _Rational?: (**__todo__ options) -> UnionType
515
+
516
+ # Creates a SetType instance.
517
+ #
518
+ # @example
519
+ # type = _Set
520
+ # type.validate(Set[1, 2, 3]) # => true
521
+ #
522
+ # @param options [Hash] additional configuration options
523
+ #
524
+ # @return [Domainic::Type::SetType] the created type
525
+ def _Set: (**__todo__ options) -> SetType
526
+
527
+ # Creates a nilable SetType instance.
528
+ #
529
+ # @example
530
+ # type = _Set?
531
+ # type.validate(Set[1, 2, 3]) # => true
532
+ # type.validate(nil) # => true
533
+ #
534
+ # @param options [Hash] additional configuration options
535
+ #
536
+ # @return [Domainic::Type::UnionType] the created type (Set or NilClass)
537
+ def _Set?: (**__todo__ options) -> UnionType
538
+
398
539
  # Creates a StringType instance.
399
540
  #
400
541
  # @example
@@ -467,6 +608,30 @@ module Domainic
467
608
  # @return [Domainic::Type::UnionType] the created type (TimeType or NilClass)
468
609
  def _Time?: (**__todo__ options) -> UnionType
469
610
 
611
+ # Creates a TimestampType instance.
612
+ #
613
+ # TimestampType restricts values to valid timestamps.
614
+ #
615
+ # @example
616
+ # type = _Timestamp
617
+ # type.validate(1640995200) # => true
618
+ #
619
+ # @param options [Hash] additional configuration options
620
+ #
621
+ # @return [Domainic::Type::TimestampType] the created type
622
+ def _Timestamp: (**__todo__ options) -> TimestampType
623
+
624
+ # Creates a nilable TimestampType instance.
625
+ #
626
+ # @example
627
+ # _Timestamp? === 1640995200 # => true
628
+ # _Timestamp? === nil # => true
629
+ #
630
+ # @param options [Hash] additional configuration options
631
+ #
632
+ # @return [Domainic::Type::UnionType] the created type (TimestampType or NilClass)
633
+ def _Timestamp?: (**__todo__ options) -> UnionType
634
+
470
635
  # Creates a URIType instance.
471
636
  #
472
637
  # URIType restricts values to valid URIs.
@@ -0,0 +1,96 @@
1
+ module Domainic
2
+ module Type
3
+ # A type for validating and constraining `Complex` numbers.
4
+ #
5
+ # This type extends `NumericBehavior` to provide a fluent interface for numeric-specific validations such as
6
+ # polarity and divisibility checks.
7
+ #
8
+ # @example Validating a `Complex` value
9
+ # type = Domainic::Type::ComplexType.new
10
+ # type.validate!(Complex(3, 4)) # => true
11
+ #
12
+ # @example Enforcing constraints
13
+ # type = Domainic::Type::ComplexType.new
14
+ # type.being_positive.validate!(Complex(42, 0)) # => raises TypeError
15
+ #
16
+ # @author {https://aaronmallen.me Aaron Allen}
17
+ # @since 0.1.0
18
+ class ComplexType
19
+ extend Behavior::ClassMethods
20
+
21
+ include Behavior
22
+
23
+ include Behavior::NumericBehavior
24
+
25
+ # Constrain the Complex real to be divisible by a given divisor.
26
+ #
27
+ # @param arguments [Array<Numeric>] a list of arguments, typically one divisor
28
+ # @param options [Hash] additional options such as tolerance for floating-point checks
29
+ # @option options [Numeric] :divisor the divisor to check for divisibility
30
+ # @option options [Numeric] :tolerance the tolerance for floating-point checks
31
+ #
32
+ # @return [self] the current instance for chaining
33
+ def being_divisible_by: (*Numeric arguments, ?divisor: Numeric, ?tolerance: Numeric) -> Behavior
34
+
35
+ alias being_multiple_of being_divisible_by
36
+
37
+ alias divisible_by being_divisible_by
38
+
39
+ alias multiple_of being_divisible_by
40
+
41
+ # Constrain the Complex real to be even.
42
+ #
43
+ # @return [self] the current instance for chaining
44
+ def being_even: () -> Behavior
45
+
46
+ alias even being_even
47
+
48
+ alias not_being_odd being_even
49
+
50
+ # Constrain the Complex real to be negative.
51
+ #
52
+ # @return [self] the current instance for chaining
53
+ def being_negative: () -> Behavior
54
+
55
+ alias negative being_negative
56
+
57
+ alias not_being_positive being_negative
58
+
59
+ # Constrain the Complex real value to be odd.
60
+ #
61
+ # @return [self] the current instance for chaining
62
+ def being_odd: () -> Behavior
63
+
64
+ alias odd being_odd
65
+
66
+ alias not_being_even being_odd
67
+
68
+ # Constrain the Complex real to be positive.
69
+ #
70
+ # @return [self] the current instance for chaining
71
+ def being_positive: () -> Behavior
72
+
73
+ alias positive being_positive
74
+
75
+ alias not_being_negative being_positive
76
+
77
+ # Constrain the Complex real to not be divisible by a specific divisor.
78
+ #
79
+ # @note the divisor MUST be provided as an argument or in the options Hash.
80
+ #
81
+ # @param arguments [Array<Numeric>] a list of arguments, typically one divisor
82
+ # @param options [Hash] additional options such as tolerance for floating-point checks
83
+ # @option options [Numeric] :divisor the divisor to check for divisibility
84
+ # @option options [Numeric] :tolerance the tolerance for floating-point checks
85
+ #
86
+ # @return [self] the current instance for chaining
87
+ def not_being_divisible_by: (*Numeric arguments, ?divisor: Numeric, ?tolerance: Numeric) -> Behavior
88
+
89
+ alias not_being_multiple_of not_being_divisible_by
90
+
91
+ alias not_divisible_by not_being_divisible_by
92
+
93
+ alias not_multiple_of not_being_divisible_by
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ module Domainic
2
+ module Type
3
+ # A type for validating `Range` objects with comprehensive constraints.
4
+ #
5
+ # This class allows flexible validation of ranges, supporting type checks,
6
+ # inclusion/exclusion of values, and range-specific behaviors such as bounds validation.
7
+ # It integrates with `EnumerableBehavior` for enumerable-style validations
8
+ # (e.g., size constraints, element presence).
9
+ #
10
+ # Key features:
11
+ # - Ensures the value is a `Range`.
12
+ # - Supports constraints for range boundaries (`begin` and `end`).
13
+ # - Provides validations for inclusion and exclusion of values.
14
+ # - Leverages `EnumerableBehavior` for size and collection-style constraints.
15
+ #
16
+ # @example Basic usage
17
+ # type = RangeType.new
18
+ # type.having_bounds(1, 10) # Validates range bounds (inclusive or exclusive).
19
+ # type.containing(5) # Ensures value is within the range.
20
+ # type.not_containing(15) # Ensures value is not within the range.
21
+ #
22
+ # @example Integration with EnumerableBehavior
23
+ # type = RangeType.new
24
+ # type.having_size(10) # Validates size (total elements in the range).
25
+ # type.containing_exactly(3, 7) # Validates specific values within the range.
26
+ #
27
+ # @example Flexible boundaries
28
+ # type = RangeType.new
29
+ # type.having_bounds(1, 10, exclusive: true) # Upper and lower bounds are exclusive.
30
+ #
31
+ # @author {https://aaronmallen.me Aaron Allen}
32
+ # @since 0.1.0
33
+ class RangeType
34
+ extend Behavior::ClassMethods
35
+
36
+ include Behavior
37
+
38
+ include Behavior::EnumerableBehavior
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ module Domainic
2
+ module Type
3
+ # A type for validating Rational numbers.
4
+ #
5
+ # This type ensures values are of type `Rational` and supports a range of
6
+ # constraints for numerical validation, such as positivity, negativity,
7
+ # and divisibility. It integrates with `NumericBehavior` to provide a
8
+ # consistent and fluent interface for numeric constraints.
9
+ #
10
+ # @example Validating a positive Rational number
11
+ # type = Domainic::Type::RationalType.new
12
+ # type.being_positive.validate!(Rational(3, 4)) # => true
13
+ #
14
+ # @example Validating divisibility
15
+ # type = Domainic::Type::RationalType.new
16
+ # type.being_divisible_by(1).validate!(Rational(3, 1)) # => true
17
+ #
18
+ # @example Using constraints with chaining
19
+ # type = Domainic::Type::RationalType.new
20
+ # type.being_greater_than(0).being_less_than(1).validate!(Rational(1, 2)) # => true
21
+ #
22
+ # @author {https://aaronmallen.me Aaron Allen}
23
+ # @since 0.1.0
24
+ class RationalType
25
+ extend Behavior::ClassMethods
26
+
27
+ include Behavior
28
+
29
+ include Behavior::NumericBehavior
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ module Domainic
2
+ module Type
3
+ # A type for validating and constraining `BigDecimal` objects.
4
+ #
5
+ # This type extends `NumericBehavior` to provide a fluent interface for numeric-specific validations such as being
6
+ # positive, being within a range, or satisfying divisibility rules.
7
+ #
8
+ # @example Validating a `BigDecimal` value
9
+ # type = Domainic::Type::BigDecimalType.new
10
+ # type.validate!(BigDecimal('3.14')) # => true
11
+ #
12
+ # @example Enforcing constraints
13
+ # type = Domainic::Type::BigDecimalType.new
14
+ # type.being_positive.validate!(BigDecimal('42')) # => true
15
+ # type.being_positive.validate!(BigDecimal('-42')) # raises TypeError
16
+ #
17
+ # @author {https://aaronmallen.me Aaron Allen}
18
+ # @since 0.1.0
19
+ class BigDecimalType
20
+ extend Behavior::ClassMethods
21
+
22
+ include Behavior
23
+
24
+ include Behavior::NumericBehavior
25
+ end
26
+ end
27
+ end