Module: Windoo::Validate
- Defined in:
- lib/windoo/validate.rb
Overview
A collection of methods implementing data constraints
Some of these methods can take multiple input types, such as a String or an number. All of them will either raise an exception if the value isn’t valid, or will return a standardized form of the input (e.g. a number or a Time, even if given a String)
Class Method Summary collapse
-
.array_constraints(val, attr_def:, attr_name: nil) ⇒ Object
run the array constraint validations for an array value.
-
.boolean(val, attr_name: nil, msg: nil) ⇒ Boolean
Confirm that the given value is a boolean value, accepting strings and symbols and returning real booleans as needed Accepts: true, false, ‘true’, ‘false’, ‘yes’, ‘no’, ‘t’,‘f’, ‘y’, or ‘n’ as strings or symbols, case insensitive.
-
.class_instance(val, klass:, attr_name: nil, msg: nil) ⇒ Object
validate that a value is of a specific class.
-
.container_for_new_object(new_object_class:, container: nil) ⇒ Object?
confirm we were given a valid container when creating.
-
.float(val, attr_name: nil, msg: nil) ⇒ Float
Confirm that a value is a Float or a string representation of a Float Return the Float, or raise an error.
-
.fully_validate_integer(val, attr_def:, attr_name: nil) ⇒ Object
run all the possible validations on an integer.
-
.fully_validate_number(val, attr_def:, attr_name: nil) ⇒ Object
run all the possible validations on a ‘number’.
-
.fully_validate_string(val, attr_def:, attr_name: nil) ⇒ Object
run all the possible validations on a string.
-
.in_enum(val, enum:, attr_name: nil, msg: nil) ⇒ Object
Does a value exist in a given enum array?.
-
.integer(val, attr_name: nil, msg: nil) ⇒ Integer
Confirm that a value is an integer or a string representation of an integer.
-
.json_attr(val, attr_def:, attr_name: nil) ⇒ Boolean
Validate that a value is valid based on its definition in an objects OAPI_PROPERTIES constant.
-
.matches_pattern(val, pattern:, attr_name: nil, msg: nil) ⇒ Object
Does a string match a given regular expression?.
-
.max_items(val, max:, attr_name: nil, msg: nil) ⇒ String
validate that the given value contains no more than some maximum number of items.
-
.max_length(val, max:, attr_name: nil, msg: nil) ⇒ String
validate that the given value’s length is less than or equal to some maximum.
-
.maximum(val, max:, attr_name: nil, exclusive: false, msg: nil) ⇒ String
validate that the given value is less than or equal to some maximum.
-
.min_items(val, min:, attr_name: nil, msg: nil) ⇒ String
validate that the given value contains at least some minimum number of items.
-
.min_length(val, min:, attr_name: nil, msg: nil) ⇒ String
validate that the given value’s length is greater than or equal to some minimum.
-
.minimum(val, min:, attr_name: nil, exclusive: false, msg: nil) ⇒ String
validate that the given value is greater than or equal to some minimum.
-
.multiple_of(val, multiplier:, attr_name: nil, msg: nil) ⇒ String
Validate that a given number is multiple of some other given number.
-
.not_nil(val, attr_name: nil, msg: nil) ⇒ Object
validate that a value is not nil.
-
.number(val, attr_name: nil, msg: nil) ⇒ Integer
Confirm that a value is an number or a string representation of an number.
-
.object(val, attr_name: nil, msg: nil) ⇒ Hash
Confirm that a value is a Hash Return the Hash, or raise an error.
-
.raise_invalid_data_error(msg) ⇒ Object
Thes methods all raise this error.
-
.string(val, attr_name: nil, msg: nil, to_s: false) ⇒ Hash
Confirm that a value is a String Return the String, or raise an error.
-
.symbol(val, attr_name: nil, msg: nil) ⇒ Symbol
Confirm that a value is a Symbol, or can be coerced into one Return the Symbol, or raise an error.
-
.time(val, attr_name: nil, msg: nil) ⇒ Time
Confirm that a value is a Time, or can be parsed into.
-
.unique_array(val, attr_name: nil, msg: nil) ⇒ Object
validate that an array has only unique items, no duplicate values.
-
.validate_numeric_constraints(val, attr_def:, attr_name: nil) ⇒ Object
run the numeric constraint validations for any numeric value The number itself must already be validated.
Class Method Details
.array_constraints(val, attr_def:, attr_name: nil) ⇒ Object
run the array constraint validations for an array value. The individual array items must already be validated
125 126 127 128 129 130 131 |
# File 'lib/windoo/validate.rb', line 125 def self.array_constraints(val, attr_def:, attr_name: nil) min_items val, min: attr_def[:minItems], attr_name: attr_name if attr_def[:minItems] max_items val, max: attr_def[:maxItems], attr_name: attr_name if attr_def[:maxItems] unique_array val, attr_name: attr_name if attr_def[:uniqueItems] val end |
.boolean(val, attr_name: nil, msg: nil) ⇒ Boolean
Confirm that the given value is a boolean value, accepting strings and symbols and returning real booleans as needed Accepts: true, false, ‘true’, ‘false’, ‘yes’, ‘no’, ‘t’,‘f’, ‘y’, or ‘n’ as strings or symbols, case insensitive
TODO: use this throughout ruby-jss
170 171 172 173 174 175 176 |
# File 'lib/windoo/validate.rb', line 170 def self.boolean(val, attr_name: nil, msg: nil) return val if Windoo::TRUE_FALSE.include? val return true if val.to_s =~ /^(t(rue)?|y(es)?)$/i return false if val.to_s =~ /^(f(alse)?|no?)$/i raise_invalid_data_error(msg || "#{attr_name} value must be boolean true or false, or an equivalent string or symbol") end |
.class_instance(val, klass:, attr_name: nil, msg: nil) ⇒ Object
validate that a value is of a specific class
143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/windoo/validate.rb', line 143 def self.class_instance(val, klass:, attr_name: nil, msg: nil) return val if val.instance_of? klass # try to instantiate the class with the value. It should raise an error # if not good klass.new val rescue StandardError => e unless msg msg = +"#{attr_name} value must be a #{klass}, or #{klass}.new must accept it as the only parameter," msg << "but #{klass}.new raised: #{e.class}: #{e}" end raise_invalid_data_error(msg) end |
.container_for_new_object(new_object_class:, container: nil) ⇒ Object?
confirm we were given a valid container when creating
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
# File 'lib/windoo/validate.rb', line 529 def self.container_for_new_object(new_object_class:, container: nil) # software titles don't have containers. return if new_object_class == Windoo::SoftwareTitle unless container raise Windoo::UnsupportedError, 'All new objects other than SoftwareTitle must pass in a container: object' end unless new_object_class::CONTAINER_CLASS == container.class raise Windoo::InvalidDataError, "The container for new #{new_object_class} objects must be a #{new_object_class::CONTAINER_CLASS} object" end container end |
.float(val, attr_name: nil, msg: nil) ⇒ Float
Confirm that a value is a Float or a string representation of a Float Return the Float, or raise an error
229 230 231 232 233 234 235 |
# File 'lib/windoo/validate.rb', line 229 def self.float(val, attr_name: nil, msg: nil) val = val.to_f if val.is_a?(Integer) val = val.to_f if val.is_a?(String) && (val.j_float? || val.j_integer?) return val if val.is_a? Float raise_invalid_data_error(msg || "#{attr_name} value must be an floating point number") end |
.fully_validate_integer(val, attr_def:, attr_name: nil) ⇒ Object
run all the possible validations on an integer
93 94 95 96 |
# File 'lib/windoo/validate.rb', line 93 def self.fully_validate_integer(val, attr_def:, attr_name: nil) val = integer val, attr_name: attr_name validate_numeric_constraints(val, attr_def: attr_def, attr_name: attr_name) end |
.fully_validate_number(val, attr_def:, attr_name: nil) ⇒ Object
run all the possible validations on a ‘number’
99 100 101 102 103 104 105 106 107 |
# File 'lib/windoo/validate.rb', line 99 def self.fully_validate_number(val, attr_def:, attr_name: nil) val = if %w[float double].include? attr_def[:format] float val, attr_name: attr_name else number val, attr_name: attr_name end validate_numeric_constraints(val, attr_def: attr_def, attr_name: attr_name) end |
.fully_validate_string(val, attr_def:, attr_name: nil) ⇒ Object
run all the possible validations on a string
82 83 84 85 86 87 88 89 90 |
# File 'lib/windoo/validate.rb', line 82 def self.fully_validate_string(val, attr_def:, attr_name: nil) val = string val, attr_name: attr_name min_length val, min: attr_def[:min_length], attr_name: attr_name if attr_def[:min_length] max_length val, max: attr_def[:max_length], attr_name: attr_name if attr_def[:max_length] matches_pattern val, attr_def[:pattern], attr_name: attr_name if attr_def[:pattern] val end |
.in_enum(val, enum:, attr_name: nil, msg: nil) ⇒ Object
Does a value exist in a given enum array?
498 499 500 501 502 |
# File 'lib/windoo/validate.rb', line 498 def self.in_enum(val, enum:, attr_name: nil, msg: nil) return val if enum.include? val raise_invalid_data_error(msg || "#{attr_name} value must be one of: #{enum.join ', '}") end |
.integer(val, attr_name: nil, msg: nil) ⇒ Integer
Confirm that a value is an integer or a string representation of an integer. Return the integer, or raise an error
213 214 215 216 217 218 |
# File 'lib/windoo/validate.rb', line 213 def self.integer(val, attr_name: nil, msg: nil) val = val.to_i if val.is_a?(String) && val.j_integer? return val if val.is_a? Integer raise_invalid_data_error(msg || "#{attr_name} value must be an integer") end |
.json_attr(val, attr_def:, attr_name: nil) ⇒ Boolean
Validate that a value is valid based on its definition in an objects OAPI_PROPERTIES constant.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/windoo/validate.rb', line 36 def self.json_attr(val, attr_def:, attr_name: nil) # check that the new val is not nil if its required val = not_nil(val, attr_name: attr_name) if attr_def[:required] # if the new val is nil here, then nil is OK andd we shouldn't # check anything else return val if val.nil? val = case attr_def[:class] when :Boolean boolean val, attr_name: attr_name when :String fully_validate_string(val, attr_def: attr_def, attr_name: attr_name) when :Integer fully_validate_integer(val, attr_def: attr_def, attr_name: attr_name) when :Number fully_validate_number(val, attr_def: attr_def, attr_name: attr_name) when :Hash hash val, attr_name: attr_name when :Symbol symbol val, attr_name: attr_name when :Time time val, attr_name: attr_name else val end # case # Now that the val is in whatever correct format after the above tests, # we test for enum membership if needed # otherwise, just return the val if attr_def[:enum] in_enum val, enum: attr_def[:enum], attr_name: attr_name else val end end |
.matches_pattern(val, pattern:, attr_name: nil, msg: nil) ⇒ Object
Does a string match a given regular expression?
514 515 516 517 518 |
# File 'lib/windoo/validate.rb', line 514 def self.matches_pattern(val, pattern:, attr_name: nil, msg: nil) return val if val =~ pattern raise_invalid_data_error(msg || "#{attr_name} value does not match RegExp: #{pattern}") end |
.max_items(val, max:, attr_name: nil, msg: nil) ⇒ String
validate that the given value contains no more than some maximum number of items
While this is intended for Arrays, it will work for any object that responds to #size
452 453 454 455 456 457 |
# File 'lib/windoo/validate.rb', line 452 def self.max_items(val, max:, attr_name: nil, msg: nil) raise ArgumentError, 'max must be a number' unless max.is_a?(Numeric) return val if val.size <= max raise_invalid_data_error(msg || "#{attr_name} value must contain no more than #{max} items") end |
.max_length(val, max:, attr_name: nil, msg: nil) ⇒ String
validate that the given value’s length is less than or equal to some maximum
While this is intended for Strings, it will work for any object that responds to #length
412 413 414 415 416 417 |
# File 'lib/windoo/validate.rb', line 412 def self.max_length(val, max:, attr_name: nil, msg: nil) raise ArgumentError, 'max must be a number' unless max.is_a?(Numeric) return val if val.length <= max raise_invalid_data_error(msg || "length of #{attr_name} value must be <= #{max}") end |
.maximum(val, max:, attr_name: nil, exclusive: false, msg: nil) ⇒ String
validate that the given value is less than or equal to some maximum
While intended for Numbers, this will work for any Comparable objects
If exclusive, the max value is excluded from the range and the value must be less than the max.
347 348 349 350 351 352 353 354 |
# File 'lib/windoo/validate.rb', line 347 def self.maximum(val, max:, attr_name: nil, exclusive: false, msg: nil) if exclusive return val if val < max elsif val <= max return val end raise_invalid_data_error(msg || "#{attr_name} value must be <= #{max}") end |
.min_items(val, min:, attr_name: nil, msg: nil) ⇒ String
validate that the given value contains at least some minimum number of items
While this is intended for Arrays, it will work for any object that responds to #size
432 433 434 435 436 437 |
# File 'lib/windoo/validate.rb', line 432 def self.min_items(val, min:, attr_name: nil, msg: nil) raise ArgumentError, 'min must be a number' unless min.is_a?(Numeric) return val if val.size >= min raise_invalid_data_error(msg || "#{attr_name} value must contain at least #{min} items") end |
.min_length(val, min:, attr_name: nil, msg: nil) ⇒ String
validate that the given value’s length is greater than or equal to some minimum
While this is intended for Strings, it will work for any object that responds to #length
392 393 394 395 396 397 |
# File 'lib/windoo/validate.rb', line 392 def self.min_length(val, min:, attr_name: nil, msg: nil) raise ArgumentError, 'min must be a number' unless min.is_a?(Numeric) return val if val.length >= min raise_invalid_data_error(msg || "length of #{attr_name} value must be >= #{min}") end |
.minimum(val, min:, attr_name: nil, exclusive: false, msg: nil) ⇒ String
validate that the given value is greater than or equal to some minimum
If exclusive, the min value is excluded from the range and the value must be greater than the min.
While intended for Numbers, this will work for any Comparable objects
320 321 322 323 324 325 326 327 |
# File 'lib/windoo/validate.rb', line 320 def self.minimum(val, min:, attr_name: nil, exclusive: false, msg: nil) if exclusive return val if val > min elsif val >= min return val end raise_invalid_data_error(msg || "#{attr_name} value must be >= #{min}") end |
.multiple_of(val, multiplier:, attr_name: nil, msg: nil) ⇒ String
Validate that a given number is multiple of some other given number
367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/windoo/validate.rb', line 367 def self.multiple_of(val, multiplier:, attr_name: nil, msg: nil) unless multiplier.is_a?(Numeric) && multiplier.positive? raise ArgumentError, 'multiplier must be a positive number' end raise Windoo::InvalidDataError, 'Value must be a number' unless val.is_a?(Numeric) return val if (val % multiplier).zero? raise_invalid_data_error(msg || "#{attr_name} value must be a multiple of #{multiplier}") end |
.not_nil(val, attr_name: nil, msg: nil) ⇒ Object
validate that a value is not nil
482 483 484 485 486 |
# File 'lib/windoo/validate.rb', line 482 def self.not_nil(val, attr_name: nil, msg: nil) return val unless val.nil? raise_invalid_data_error(msg || "#{attr_name} value may not be nil") end |
.number(val, attr_name: nil, msg: nil) ⇒ Integer
Confirm that a value is an number or a string representation of an number. Return the number, or raise an error
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/windoo/validate.rb', line 187 def self.number(val, attr_name: nil, msg: nil) if val.ia_a?(Integer) || val.is_a?(Float) return val elsif val.is_a?(String) if val.j_integer? return val.to_i elsif val.j_float? return val.to_f end end raise_invalid_data_error(msg || "#{attr_name} value must be a number") end |
.object(val, attr_name: nil, msg: nil) ⇒ Hash
Confirm that a value is a Hash Return the Hash, or raise an error
246 247 248 249 250 |
# File 'lib/windoo/validate.rb', line 246 def self.object(val, attr_name: nil, msg: nil) return val if val.is_a? Hash raise_invalid_data_error(msg || "#{attr_name} value must be a Hash") end |
.raise_invalid_data_error(msg) ⇒ Object
Thes methods all raise this error
21 22 23 |
# File 'lib/windoo/validate.rb', line 21 def self.raise_invalid_data_error(msg) raise Windoo::InvalidDataError, msg end |
.string(val, attr_name: nil, msg: nil, to_s: false) ⇒ Hash
Confirm that a value is a String Return the String, or raise an error
295 296 297 298 299 300 |
# File 'lib/windoo/validate.rb', line 295 def self.string(val, attr_name: nil, msg: nil, to_s: false) val = val.to_s if to_s return val if val.is_a? String raise_invalid_data_error(msg || "#{attr_name} value must be a String") end |
.symbol(val, attr_name: nil, msg: nil) ⇒ Symbol
Confirm that a value is a Symbol, or can be coerced into one Return the Symbol, or raise an error
261 262 263 264 265 |
# File 'lib/windoo/validate.rb', line 261 def self.symbol(val, attr_name: nil, msg: nil) return val.to_sym if val.respond_to? :to_sym raise_invalid_data_error(msg || "#{attr_name} value must be a Symbol") end |
.time(val, attr_name: nil, msg: nil) ⇒ Time
Confirm that a value is a Time, or can be parsed into
Return the ISO8601 formatted String, or raise an error
277 278 279 280 281 |
# File 'lib/windoo/validate.rb', line 277 def self.time(val, attr_name: nil, msg: nil) val.is_a?(Time) ? val : Time.parse(val.to_s) rescue StandardError raise_invalid_data_error(msg || "#{attr_name} value must be a Time, or a String to be used with Time.parse") end |
.unique_array(val, attr_name: nil, msg: nil) ⇒ Object
validate that an array has only unique items, no duplicate values
467 468 469 470 471 472 |
# File 'lib/windoo/validate.rb', line 467 def self.unique_array(val, attr_name: nil, msg: nil) raise ArgumentError, 'Value must be an Array' unless val.is_a?(Array) return val if val.uniq.size == val.size raise_invalid_data_error(msg || "#{attr_name} value must contain only unique items") end |
.validate_numeric_constraints(val, attr_def:, attr_name: nil) ⇒ Object
run the numeric constraint validations for any numeric value The number itself must already be validated
111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/windoo/validate.rb', line 111 def self.validate_numeric_constraints(val, attr_def:, attr_name: nil) ex_min = attr_def[:exclusive_minimum] ex_max = attr_def[:exclusive_maximum] mult_of = attr_def[:multiple_of] minimum val, min: attr_def[:minimum], exclusive: ex_min, attr_name: attr_name if attr_def[:minimum] maximum val, max: attr_def[:maximum], exclusive: ex_max, attr_name: attr_name if attr_def[:maximum] multiple_of val, multiplier: mult_of, attr_name: attr_name if mult_of val end |