Class: Philiprehberger::GuardClause::Guard

Inherits:
Object
  • Object
show all
Defined in:
lib/philiprehberger/guard_clause/guard.rb

Overview

Guard object that performs validation checks on a value

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, soft: false) ⇒ Guard

Returns a new instance of Guard.

Parameters:

  • value (Object)

    the value to guard

  • soft (Boolean) (defaults to: false)

    when true, collect errors instead of raising



17
18
19
20
21
# File 'lib/philiprehberger/guard_clause/guard.rb', line 17

def initialize(value, soft: false)
  @value = value
  @soft = soft
  @errors = []
end

Instance Attribute Details

#errorsArray<String> (readonly)

Returns collected errors (soft mode only).

Returns:

  • (Array<String>)

    collected errors (soft mode only)



27
28
29
# File 'lib/philiprehberger/guard_clause/guard.rb', line 27

def errors
  @errors
end

#valueObject (readonly)

Returns the guarded value.

Returns:

  • (Object)

    the guarded value



24
25
26
# File 'lib/philiprehberger/guard_clause/guard.rb', line 24

def value
  @value
end

Instance Method Details

#between(min, max, message: nil) ⇒ Guard

Assert the value is between min and max (inclusive)

Parameters:

  • min (Comparable)

    the minimum bound

  • max (Comparable)

    the maximum bound

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



129
130
131
132
133
134
# File 'lib/philiprehberger/guard_clause/guard.rb', line 129

def between(min, max, message: nil)
  if @value.respond_to?(:<) && @value.respond_to?(:>) && (@value < min || @value > max)
    handle_violation(message || "value must be between #{min} and #{max}")
  end
  self
end

#ends_with(suffix, message: nil) ⇒ Guard

Assert the value ends with the given suffix

Parameters:

  • suffix (String)

    the expected suffix

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



187
188
189
190
191
192
# File 'lib/philiprehberger/guard_clause/guard.rb', line 187

def ends_with(suffix, message: nil)
  if @value.respond_to?(:end_with?) && !@value.end_with?(suffix)
    handle_violation(message || "value must end with #{suffix.inspect}")
  end
  self
end

#format(pattern, message: nil) ⇒ Guard

Assert the value matches a pattern

Parameters:

  • pattern (Regexp, Symbol)

    a Regexp or a built-in pattern name (:uuid, :email)

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



214
215
216
217
218
219
220
221
222
# File 'lib/philiprehberger/guard_clause/guard.rb', line 214

def format(pattern, message: nil)
  regex = if pattern.is_a?(Symbol)
            BUILT_IN_PATTERNS.fetch(pattern) { raise ArgumentError, "unknown built-in pattern: #{pattern.inspect}" }
          else
            pattern
          end
  handle_violation(message || "value must match #{pattern.inspect} format") unless regex.match?(@value.to_s)
  self
end

#gte(n, message = nil) ⇒ Guard

Assert the value is greater than or equal to n

Parameters:

  • n (Numeric)

    the minimum value

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



66
67
68
69
70
71
# File 'lib/philiprehberger/guard_clause/guard.rb', line 66

def gte(n, message = nil)
  if @value.respond_to?(:>=) && @value < n
    handle_violation(message || "value must be greater than or equal to #{n}")
  end
  self
end

#is_a(type, message: nil) ⇒ Guard

Assert the value is an instance of the given type

Parameters:

  • type (Class)

    the expected type

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



118
119
120
121
# File 'lib/philiprehberger/guard_clause/guard.rb', line 118

def is_a(type, message: nil)
  handle_violation(message || "value must be a #{type}") unless @value.is_a?(type)
  self
end

#lte(n, message = nil) ⇒ Guard

Assert the value is less than or equal to n

Parameters:

  • n (Numeric)

    the maximum value

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



78
79
80
81
# File 'lib/philiprehberger/guard_clause/guard.rb', line 78

def lte(n, message = nil)
  handle_violation(message || "value must be less than or equal to #{n}") if @value.respond_to?(:<=) && @value > n
  self
end

#matches(regex, message = nil) ⇒ Guard

Assert the value matches a regex pattern

Parameters:

  • regex (Regexp)

    the pattern to match

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



88
89
90
91
# File 'lib/philiprehberger/guard_clause/guard.rb', line 88

def matches(regex, message = nil)
  handle_violation(message || "value must match #{regex.inspect}") unless regex.match?(@value.to_s)
  self
end

#max_length(n, message: nil) ⇒ Guard

Assert the value has a maximum length

Parameters:

  • n (Integer)

    the maximum length

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



153
154
155
156
157
158
# File 'lib/philiprehberger/guard_clause/guard.rb', line 153

def max_length(n, message: nil)
  if @value.respond_to?(:length) && @value.length > n
    handle_violation(message || "value must have a maximum length of #{n}")
  end
  self
end

#min_length(n, message: nil) ⇒ Guard

Assert the value has a minimum length

Parameters:

  • n (Integer)

    the minimum length

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



141
142
143
144
145
146
# File 'lib/philiprehberger/guard_clause/guard.rb', line 141

def min_length(n, message: nil)
  if @value.respond_to?(:length) && @value.length < n
    handle_violation(message || "value must have a minimum length of #{n}")
  end
  self
end

#not_empty(message = nil) ⇒ Guard

Assert the value is not empty

Parameters:

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



47
48
49
50
# File 'lib/philiprehberger/guard_clause/guard.rb', line 47

def not_empty(message = nil)
  handle_violation(message || 'value must not be empty') if @value.respond_to?(:empty?) && @value.empty?
  self
end

#not_equal(other, message = nil) ⇒ Guard

Assert the value is not equal to another value

Parameters:

  • other (Object)

    the value to compare against

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



108
109
110
111
# File 'lib/philiprehberger/guard_clause/guard.rb', line 108

def not_equal(other, message = nil)
  handle_violation(message || "value must not be equal to #{other.inspect}") if @value == other
  self
end

#not_nil(message = nil) ⇒ Guard

Assert the value is not nil

Parameters:

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



38
39
40
41
# File 'lib/philiprehberger/guard_clause/guard.rb', line 38

def not_nil(message = nil)
  handle_violation(message || 'value must not be nil') if @value.nil?
  self
end

#one_of(arr, message = nil) ⇒ Guard

Assert the value is one of the given options

Parameters:

  • arr (Array)

    the allowed values

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



98
99
100
101
# File 'lib/philiprehberger/guard_clause/guard.rb', line 98

def one_of(arr, message = nil)
  handle_violation(message || "value must be one of #{arr.inspect}") unless arr.include?(@value)
  self
end

#positive(message = nil) ⇒ Guard

Assert the value is positive

Parameters:

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



56
57
58
59
# File 'lib/philiprehberger/guard_clause/guard.rb', line 56

def positive(message = nil)
  handle_violation(message || 'value must be positive') if @value.respond_to?(:>) && @value <= 0
  self
end

#present(message: nil) ⇒ Guard

Assert the value is not nil, not empty, and not blank (for strings)

Parameters:

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



198
199
200
201
202
203
204
205
206
207
# File 'lib/philiprehberger/guard_clause/guard.rb', line 198

def present(message: nil)
  if @value.nil?
    handle_violation(message || 'value must be present')
  elsif @value.respond_to?(:empty?) && @value.empty?
    handle_violation(message || 'value must be present')
  elsif @value.is_a?(String) && @value.strip.empty?
    handle_violation(message || 'value must be present')
  end
  self
end

#satisfies(message: nil, &block) ⇒ Guard

Assert the value satisfies a custom predicate

Parameters:

  • message (String) (defaults to: nil)

    custom error message

  • block (Proc)

    the predicate block

Returns:

  • (Guard)

    self for chaining



165
166
167
168
# File 'lib/philiprehberger/guard_clause/guard.rb', line 165

def satisfies(message: nil, &block)
  handle_violation(message || 'value does not satisfy the condition') unless block.call(@value)
  self
end

#starts_with(prefix, message: nil) ⇒ Guard

Assert the value starts with the given prefix

Parameters:

  • prefix (String)

    the expected prefix

  • message (String) (defaults to: nil)

    custom error message

Returns:

  • (Guard)

    self for chaining



175
176
177
178
179
180
# File 'lib/philiprehberger/guard_clause/guard.rb', line 175

def starts_with(prefix, message: nil)
  if @value.respond_to?(:start_with?) && !@value.start_with?(prefix)
    handle_violation(message || "value must start with #{prefix.inspect}")
  end
  self
end

#valid?Boolean

Returns true if no errors were collected.

Returns:

  • (Boolean)

    true if no errors were collected



30
31
32
# File 'lib/philiprehberger/guard_clause/guard.rb', line 30

def valid?
  @errors.empty?
end