Skip to content
This repository has been archived by the owner on Feb 9, 2022. It is now read-only.

Commit

Permalink
Extract validation objects from all schemas
Browse files Browse the repository at this point in the history
[#61862446]
  • Loading branch information
Alex Stupakov and Ryan Moran committed Feb 18, 2014
1 parent 1bd4d8e commit cd10f38
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 87 deletions.
24 changes: 20 additions & 4 deletions lib/membrane/schemas/bool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@
require "membrane/schemas/base"

class Membrane::Schemas::Bool < Membrane::Schemas::Base
TRUTH_VALUES = Set.new([true, false])

def validate(object)
if !TRUTH_VALUES.include?(object)
emsg = "Expected instance of true or false, given #{object}"
BoolValidator.new(object).validate
end

class BoolValidator
TRUTH_VALUES = Set.new([true, false])

def initialize(object)
@object = object
end

def validate
if !TRUTH_VALUES.include?(@object)
fail!
end
end

private

def fail!
emsg = "Expected instance of true or false, given #{@object}"
raise Membrane::SchemaValidationError.new(emsg)
end
end
Expand Down
20 changes: 18 additions & 2 deletions lib/membrane/schemas/class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,25 @@ def initialize(klass)

# Validates whether or not the supplied object is derived from klass
def validate(object)
if !object.kind_of?(@klass)
ClassValidator.new(@klass, object).validate
end

class ClassValidator

def initialize(klass, object)
@klass = klass
@object = object
end

def validate
fail! if !@object.kind_of?(@klass)
end

private

def fail!
emsg = "Expected instance of #{@klass}," \
+ " given an instance of #{object.class}"
+ " given an instance of #{@object.class}"
raise Membrane::SchemaValidationError.new(emsg)
end
end
Expand Down
49 changes: 39 additions & 10 deletions lib/membrane/schemas/dictionary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,52 @@ def initialize(key_schema, value_schema)
end

def validate(object)
if !object.kind_of?(Hash)
emsg = "Expected instance of Hash, given instance of #{object.class}."
HashValidator.new(object).validate
MembersValidator.new(@key_schema, @value_schema, object).validate
end

class HashValidator
def initialize(object)
@object = object
end

def validate
fail!(@object.class) if !@object.kind_of?(Hash)
end

private

def fail!(klass)
emsg = "Expected instance of Hash, given instance of #{klass}."
raise Membrane::SchemaValidationError.new(emsg)
end
end

class MembersValidator
def initialize(key_schema, value_schema, object)
@key_schema = key_schema
@value_schema = value_schema
@object = object
end

errors = {}
def validate
errors = {}

object.each do |k, v|
begin
@key_schema.validate(k)
@value_schema.validate(v)
rescue Membrane::SchemaValidationError => e
errors[k] = e.to_s
@object.each do |k, v|
begin
@key_schema.validate(k)
@value_schema.validate(v)
rescue Membrane::SchemaValidationError => e
errors[k] = e.to_s
end
end

fail!(errors) if errors.size > 0
end

if errors.size > 0
private

def fail!(errors)
emsg = "{ " + errors.map { |k, e| "#{k} => #{e}" }.join(", ") + " }"
raise Membrane::SchemaValidationError.new(emsg)
end
Expand Down
37 changes: 28 additions & 9 deletions lib/membrane/schemas/enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,39 @@ class Membrane::Schemas::Enum < Membrane::Schemas::Base

def initialize(*elem_schemas)
@elem_schemas = elem_schemas
@elem_schema_str = elem_schemas.map { |s| s.to_s }.join(", ")
end

def validate(object)
@elem_schemas.each do |schema|
begin
schema.validate(object)
return nil
rescue Membrane::SchemaValidationError
EnumValidator.new(@elem_schemas, object).validate
end

class EnumValidator
def initialize(elem_schemas, object)
@elem_schemas = elem_schemas
@object = object
end

def validate
@elem_schemas.each do |schema|
begin
schema.validate(@object)
return nil
rescue Membrane::SchemaValidationError
end
end

fail!(@elem_schemas)
end

emsg = "Object #{object} doesn't validate" \
+ " against any of #{@elem_schema_str}"
raise Membrane::SchemaValidationError.new(emsg)
private

def fail!(elem_schemas)
elem_schema_str = elem_schemas.map { |s| s.to_s }.join(", ")

emsg = "Object #{@object} doesn't validate" \
+ " against any of #{elem_schema_str}"
raise Membrane::SchemaValidationError.new(emsg)
end
end

end
44 changes: 35 additions & 9 deletions lib/membrane/schemas/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,48 @@ def initialize(elem_schema)
end

def validate(object)
if !object.kind_of?(Array)
emsg = "Expected instance of Array, given instance of #{object.class}"
ArrayValidator.new(object).validate
MemberValidator.new(@elem_schema, object).validate
end

class ArrayValidator
def initialize(object)
@object = object
end

def validate
fail! if !@object.kind_of?(Array)
end

private

def fail!
emsg = "Expected instance of Array, given instance of #{@object.class}"
raise Membrane::SchemaValidationError.new(emsg)
end
end

errors = {}
class MemberValidator
def initialize(elem_schema, object)
@elem_schema = elem_schema
@object = object
end

object.each_with_index do |elem, ii|
begin
@elem_schema.validate(elem)
rescue Membrane::SchemaValidationError => e
errors[ii] = e.to_s
def validate
errors = {}

@object.each_with_index do |elem, ii|
begin
@elem_schema.validate(elem)
rescue Membrane::SchemaValidationError => e
errors[ii] = e.to_s
end
end

fail!(errors) if errors.size > 0
end

if errors.size > 0
def fail!(errors)
emsg = errors.map { |ii, e| "At index #{ii}: #{e}" }.join(", ")
raise Membrane::SchemaValidationError.new(emsg)
end
Expand Down
83 changes: 58 additions & 25 deletions lib/membrane/schemas/record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,78 @@ def initialize(schemas, optional_keys = [], strict_checking = false)
end

def validate(object)
unless object.kind_of?(Hash)
emsg = "Expected instance of Hash, given instance of #{object.class}"
raise Membrane::SchemaValidationError.new(emsg)
end
HashValidator.new(object).validate
KeyValidator.new(@optional_keys, @schemas, @strict_checking, object).validate
end

def parse(&blk)
other_record = Membrane::SchemaParser.parse(&blk)
@schemas.merge!(other_record.schemas)
@optional_keys << other_record.optional_keys

key_errors = {}
self
end

schema_keys = []
@schemas.each do |k, schema|
if object.has_key?(k)
schema_keys << k
begin
schema.validate(object[k])
rescue Membrane::SchemaValidationError => e
key_errors[k] = e.to_s
class KeyValidator
def initialize(optional_keys, schemas, strict_checking, object)
@optional_keys = optional_keys
@schemas = schemas
@strict_checking = strict_checking
@object = object
end

def validate
key_errors = {}
schema_keys = []
@schemas.each do |k, schema|
if @object.has_key?(k)
schema_keys << k
begin
schema.validate(@object[k])
rescue Membrane::SchemaValidationError => e
key_errors[k] = e.to_s
end
elsif !@optional_keys.include?(k)
key_errors[k] = "Missing key"
end
elsif !@optional_keys.include?(k)
key_errors[k] = "Missing key"
end

key_errors.merge!(validate_extra_keys(@object.keys - schema_keys)) if @strict_checking

fail!(key_errors) if key_errors.size > 0
end

if @strict_checking
extra_keys = object.keys - schema_keys
private

def validate_extra_keys(extra_keys)
extra_key_errors = {}
extra_keys.each do |k|
key_errors[k] = "was not specified in the schema"
extra_key_errors[k] = "was not specified in the schema"
end

extra_key_errors
end

if key_errors.size > 0
emsg = "{ " + key_errors.map { |k, e| "#{k} => #{e}" }.join(", ") + " }"
def fail!(errors)
emsg = "{ " + errors.map { |k, e| "#{k} => #{e}" }.join(", ") + " }"
raise Membrane::SchemaValidationError.new(emsg)
end
end

def parse(&blk)
other_record = Membrane::SchemaParser.parse(&blk)
@schemas.merge!(other_record.schemas)
@optional_keys << other_record.optional_keys
class HashValidator
def initialize(object)
@object = object
end

self
def validate
fail! unless @object.kind_of?(Hash)
end

private

def fail!
emsg = "Expected instance of Hash, given instance of #{@object.class}"
raise Membrane::SchemaValidationError.new(emsg)
end
end
end
43 changes: 37 additions & 6 deletions lib/membrane/schemas/regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,47 @@ def initialize(regexp)
end

def validate(object)
if !object.kind_of?(String)
emsg = "Expected instance of String, given instance of #{object.class}"
raise Membrane::SchemaValidationError.new(emsg)
StringValidator.new(object).validate
MatchValidator.new(@regexp, object).validate

nil
end

class StringValidator

def initialize(object)
@object = object
end

def validate
fail! if !@object.kind_of?(String)
end

if !regexp.match(object)
emsg = "Value #{object} doesn't match regexp #{@regexp}"
private

def fail!
emsg = "Expected instance of String, given instance of #{@object.class}"
raise Membrane::SchemaValidationError.new(emsg)
end

nil
end

class MatchValidator

def initialize(regexp, object)
@regexp = regexp
@object = object
end

def validate
fail! if !@regexp.match(@object)
end

private

def fail!
emsg = "Value #{@object} doesn't match regexp #{@regexp}"
raise Membrane::SchemaValidationError.new(emsg)
end
end
end
Loading

0 comments on commit cd10f38

Please sign in to comment.