Skip to content

Commit

Permalink
Implement optional values.
Browse files Browse the repository at this point in the history
  • Loading branch information
splattael committed Jan 28, 2010
1 parent 61bdf7c commit ad1e7e4
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 17 deletions.
8 changes: 5 additions & 3 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Source[http://github.com/splattael/schema_validator] | RDoc[http://rdoc.info/pro
:type => value.is_a(String),
:value => value.hash(
:src => value.is_a(String),
:height => value.is_a(Fixnum),
:width => value.is_a(Fixnum)
:height => optional_value.is_a(Fixnum),
:width => optional_value.is_a(Fixnum)
)
)
end
Expand All @@ -34,6 +34,9 @@ Source[http://github.com/splattael/schema_validator] | RDoc[http://rdoc.info/pro
}
) # => true

# :height and width are optional
deep.validate(:type => "image", :value => { :src => "/bold.gif" }) # => true

== Matchers

Following matchers are defined:
Expand All @@ -53,5 +56,4 @@ Following matchers are defined:
* Peter Suschlik

== TODO
* Implement optional arguments
* Implement and aggregate errors
40 changes: 27 additions & 13 deletions lib/schema_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,59 @@

class SchemaValidator

class Caller
class Scope
def value
SchemaValidator.new
Value.new
end

def optional_value
OptionalValue.new
end
end

class Value < SchemaValidator
end

class OptionalValue < SchemaValidator
def validate(value = nil)
puts "optional: #{value.inspect}" if $DEBUG
value.nil? || super
end
end

attr_reader :validators

def initialize(&block)
@validators = []
@validators << Caller.new.instance_eval(&block) if block
@validators << Scope.new.instance_eval(&block) if block
end

def hash(schema={})
valid? do |value|
value ||= {}
schema.all? do |(key, validator)|
validator.validate(value[key])
result = validator.validate(value[key])
puts "hash[:#{key}] = #{value[key].inspect} # => #{result.inspect}" if $DEBUG
result
end
end
end

def validate(value = nil)
if @validators.empty?
value.nil?
else
@validators.all? do |validator|
validator.call(value)
end
end
@validators.all? { |validator| validator.call(value) }
end

def call(value)
validate(value)
end
alias call validate

def valid?(&block)
@validators << block
self
end

def method_missing(method, *args, &block)
if matcher = self.class.matchers[method]
if matcher = SchemaValidator.matchers[method]
valid? do |value|
matcher.call(value, args.first)
end
Expand Down
53 changes: 52 additions & 1 deletion test/test_schema_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ def v(value=nil, &block)
end
end

class Riot::Context
def debug(&block)
old = $DEBUG
$DEBUG = true
yield
ensure
$DEBUG = old
end
end

context "SchemaValidator" do

asserts(:class) { SchemaValidator.new }.equals(SchemaValidator)

context "empty" do
asserts("validate") { v }
asserts("validate nil") { v(nil) }
asserts("validates 1") { !v(1) }
asserts("validates 1") { v(1) }
end

context "matchers" do
Expand Down Expand Up @@ -91,4 +101,45 @@ def v(value=nil, &block)

end # deep nesting

context "optional_value" do
asserts("valid nil") { v(nil) { optional_value } }
asserts("valid 1") { v(1) { optional_value } }
asserts("valid empty optional String") { v(nil) { optional_value.is_a(String) } }
asserts("valid given and String") { v("test") { optional_value.is_a(String) } }
asserts("invalid given non-String") { !v(1) { optional_value.is_a(String) } }

context "netsted" do
setup do
SchemaValidator.new do
optional_value.hash(
:image => value.hash(
:src => value.is_a(String),
:alt => optional_value.is_a(String),
:size => optional_value.hash(
:width => value.is_a(Fixnum),
:height => value.is_a(Fixnum)
)
)
)
end
end

asserts("valid empty") { topic.validate }
asserts("invalid non Hash") { !topic.validate(23) }
asserts("invalid wrong key") { !topic.validate(:type => {}) }
asserts("invalid empty image") { !topic.validate(:image => {}) }
asserts("valid all given") do
topic.validate(
:image => {
:src => "/img.gif",
:alt => "Alt",
:size => { :width => 80, :height => 80 }
}
)
end
asserts("valid minimal Hash") { topic.validate(:image => { :src => "/img.gif" }) }
asserts("invalid alt") { !topic.validate(:image => { :src => "/img.gif", :alt => 23 }) }
end
end

end

0 comments on commit ad1e7e4

Please sign in to comment.