Permalink
Browse files

Simplify again. Make deep nesting work.

  • Loading branch information...
1 parent 6723036 commit 8e91cc83d949e573ace49b3a5ead4d15ef2b7862 @splattael committed Jan 27, 2010
Showing with 82 additions and 76 deletions.
  1. +31 −58 lib/schema.rb
  2. +51 −18 test/test_schema.rb
View
@@ -2,66 +2,17 @@
class Schema
- class Validator
- attr_reader :validators
-
- def initialize(schema, &block)
- @schema = schema
- @validators = [ block ]
- end
-
- def method_missing(method, *args, &block)
- @validators.concat(@schema.send(method, *args, &block).validators)
- self
- end
-
- def validate(value)
- @validators.all? do |block|
- block.call(value)
- end
- end
-
- def size
- @validators.size
- end
-
- def inspect
- "#<%s:%x @validators=%d>" % [ self.class.name, hash, size ]
+ class Caller
+ def value
+ Schema.new
end
end
- # Schema
attr_reader :validators
- class << self
- attr_reader :matchers
- end
- @matchers = {}
-
- def self.validate(value, &block)
- Schema.new(&block).validate(value)
- end
-
def initialize(&block)
@validators = []
- instance_eval(&block) if block
- end
-
- def self.matcher(name, &block)
- @matchers[name] = proc do |value, expected|
- result = block.call(value, expected)
- puts "#{value.inspect} #{name} #{expected.inspect} => #{result.inspect}"
- result
- end
- end
-
- matcher(:equals) { |value, expected| value == expected }
- matcher(:is_a?) { |value, expected| value.is_a?(expected) }
-
- matchers.keys.each { |m| undef_method m if respond_to?(m) }
-
- def value
- Schema.new
+ @validators << Caller.new.instance_eval(&block) if block
end
def hash(schema={})
@@ -72,20 +23,20 @@ def hash(schema={})
end
end
- def validate!(value = nil)
+ def validate(value = nil)
if @validators.empty?
value.nil?
else
@validators.all? do |validator|
- validator.validate(value)
+ validator.call(value)
end
end
end
+ alias call validate
def valid?(&block)
- Validator.new(self, &block).tap do |validator|
- @validators << validator
- end
+ @validators << block
+ self
end
def method_missing(method, *args, &block)
@@ -97,4 +48,26 @@ def method_missing(method, *args, &block)
super
end
end
+
+ @matchers = {}
+ class << self
+ attr_reader :matchers
+
+ def validate(value, &block)
+ Schema.new(&block).validate(value)
+ end
+
+ def matcher(name, &block)
+ undef_method(name) if respond_to?(name)
+ @matchers[name] = proc do |value, expected|
+ result = block.call(value, expected)
+ puts "#{value.inspect} #{name} #{expected.inspect} => #{result.inspect}" if $DEBUG
+ result
+ end
+ end
+ end
+
end
+
+Schema.matcher(:equals) { |value, expected| value == expected }
+Schema.matcher(:is_a?) { |value, expected| value.is_a?(expected) }
View
@@ -2,7 +2,7 @@
class Riot::Situation
def v(value=nil, &block)
- Schema.new(&block).validate!(value)
+ Schema.new(&block).validate(value)
end
end
@@ -24,38 +24,71 @@ def v(value=nil, &block)
end
context "equals" do
- asserts("valid 1") { v(1) { equals 1 } }
- asserts("invalid 2") { !v(2) { equals 1 } }
- asserts("valid String") { v("test") { equals "test" } }
- asserts("invalid String") { !v("test") { equals "tests" } }
- asserts("invalid multiple") { !v(1) {equals 1; equals 2} }
+ asserts("valid 1") { v(1) { value.equals 1 } }
+ asserts("invalid 2") { !v(2) { value.equals 1 } }
+ asserts("valid String") { v("test") { value.equals "test" } }
+ asserts("invalid String") { !v("test") { value.equals "tests" } }
+ asserts("invalid multiple") { !v(1) { value.equals 1; value.equals 2} }
end
-
context "is_a?" do
- asserts("valid String") { v("test") { is_a?(String) } }
- asserts("invalid String") { !v(1) { is_a?(String) } }
- asserts("valid multiple") { v("test") { is_a?(String); is_a?(Object) } }
- asserts("invalid multiple") { !v("test") { is_a?(String); is_a?(Fixnum) } }
+ asserts("valid String") { v("test") { value.is_a?(String) } }
+ asserts("invalid String") { !v(1) { value.is_a?(String) } }
+ asserts("valid multiple") { v("test") { value.is_a?(String); value.is_a?(Object) } }
+ asserts("invalid multiple") { !v("test") { value.is_a?(String); value.is_a?(Fixnum) } }
end
context "chaining" do
- asserts("valid") { v(1) { is_a?(Fixnum).equals(1) }}
- asserts("invalid") { !v(1) { is_a?(Fixnum).equals(2) }}
+ asserts("valid") { v(1) { value.is_a?(Fixnum).equals(1) }}
+ asserts("invalid") { !v(1) { value.is_a?(Fixnum).equals(2) }}
end
- context "hash" do
+ context "nesting" do
setup do
Schema.new do
- hash(
+ value.hash(
:key => value.is_a?(String),
:value => value.is_a?(Fixnum)
)
end
end
- asserts("valid") { topic.validate!(:key => "fasel", :value => 23) }
- asserts("invalid") { !topic.validate!(:key => 23, :value => 23) }
- asserts("missing") { !topic.validate!(:key => "fasel") }
+ asserts("valid") { topic.validate(:key => "fasel", :value => 23) }
+ asserts("invalid") { !topic.validate(:key => 23, :value => 23) }
+ asserts("missing") { !topic.validate(:key => "fasel") }
end
+
+ context "deep nesting" do
+ setup do
+ Schema.new do
+ value.hash(
+ :image => value.hash(
+ :src => value.is_a?(String),
+ :height => value.is_a?(Fixnum)
+ ),
+ :text => value.is_a?(String)
+ )
+ end
+ end
+
+ asserts("valid") do
+ topic.validate(
+ :image => {
+ :src => "/image.gif",
+ :height => 80
+ },
+ :text => "Image"
+ )
+ end
+ asserts("invalid") do
+ !topic.validate(
+ :image => {
+ :src => "/image.gif",
+ },
+ :text => "Image"
+ )
+ end
+
+ end # deep nesting
+
end

0 comments on commit 8e91cc8

Please sign in to comment.