Module: RubstApi::Validator
- Defined in:
- lib/rubst_api/model.rb
Class Method Summary collapse
- .boolean(value) ⇒ Object
- .coerce(value, type, constraints = {}) ⇒ Object
- .constrain(value, options) ⇒ Object
- .fail_constraint(value, type, message) ⇒ Object
- .nullable?(type, constraints) ⇒ Boolean
- .type_name(type) ⇒ Object
- .validate_union(value, types, constraints) ⇒ Object
Class Method Details
.boolean(value) ⇒ Object
131 132 133 134 135 136 |
# File 'lib/rubst_api/model.rb', line 131 def boolean(value) return value if value == true || value == false return true if %w[1 true on yes].include?(value.to_s.downcase) return false if %w[0 false off no].include?(value.to_s.downcase) raise TypeError end |
.coerce(value, type, constraints = {}) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/rubst_api/model.rb', line 87 def coerce(value, type, constraints = {}) return nil if value.nil? && nullable?(type, constraints) result = if type.is_a?(Array) validate_union(value, type, constraints) elsif type.is_a?(Hash) && type.key?(:array) Array(value).map { |item| coerce(item, type[:array], {}) } elsif type.is_a?(Class) && type <= Model type.validate(value, location: []) elsif type == String then String(value) elsif type == Integer then Integer(value, exception: true) elsif type == Float then Float(value) elsif type == Numeric then Float(value) elsif type == TrueClass || type == FalseClass || type == :boolean then boolean(value) elsif type == Symbol then value.to_sym elsif type == Date then Date.parse(value.to_s) elsif type == Time || type == DateTime then Time.parse(value.to_s) elsif type == URI then URI.parse(value.to_s) elsif type == Array then Array(value) elsif type == Hash then Hash(value) elsif type.respond_to?(:call) && !type.is_a?(Class) then type.call(value) elsif value.is_a?(type) then value else raise TypeError, "expected #{type}" end constrain(result, constraints) rescue ValidationError raise rescue StandardError raise ValidationError, [{ type: type_name(type), loc: [], msg: "Input should be a valid #{type_name(type)}", input: value }] end |
.constrain(value, options) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/rubst_api/model.rb', line 138 def constrain(value, ) length = value.respond_to?(:length) ? value.length : nil fail_constraint(value, "string_too_short", "Value is too short") if [:min_length] && length && length < [:min_length] fail_constraint(value, "string_too_long", "Value is too long") if [:max_length] && length && length > [:max_length] fail_constraint(value, "greater_than", "Value must be greater than #{[:gt]}") if [:gt] && !(value > [:gt]) fail_constraint(value, "greater_than_equal", "Value must be greater than or equal to #{[:ge]}") if [:ge] && !(value >= [:ge]) fail_constraint(value, "less_than", "Value must be less than #{[:lt]}") if [:lt] && !(value < [:lt]) fail_constraint(value, "less_than_equal", "Value must be less than or equal to #{[:le]}") if [:le] && !(value <= [:le]) pattern = [:pattern] || [:regex] fail_constraint(value, "string_pattern_mismatch", "Value does not match pattern") if pattern && !(Regexp.new(pattern.to_s) =~ value.to_s) fail_constraint(value, "enum", "Value is not an allowed option") if [:enum] && ![:enum].include?(value) value end |
.fail_constraint(value, type, message) ⇒ Object
152 153 154 |
# File 'lib/rubst_api/model.rb', line 152 def fail_constraint(value, type, ) raise ValidationError, [{ type:, loc: [], msg: , input: value }] end |
.nullable?(type, constraints) ⇒ Boolean
118 |
# File 'lib/rubst_api/model.rb', line 118 def nullable?(type, constraints) = constraints[:nullable] || (type.is_a?(Array) && type.include?(NilClass)) |
.type_name(type) ⇒ Object
156 157 158 159 |
# File 'lib/rubst_api/model.rb', line 156 def type_name(type) { Integer => "integer", Float => "number", String => "string", TrueClass => "boolean", FalseClass => "boolean", Hash => "object", Array => "array" }[type] || type.to_s.downcase end |
.validate_union(value, types, constraints) ⇒ Object
120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rubst_api/model.rb', line 120 def validate_union(value, types, constraints) return nil if value.nil? && types.include?(NilClass) failures = [] types.reject { |type| type == NilClass }.each do |type| return coerce(value, type, constraints) rescue ValidationError => e failures.concat(e.errors) end raise ValidationError, failures end |