valuedate 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/lib/valuedate.rb CHANGED
@@ -1,5 +1,22 @@
1
1
  class Valuedate
2
2
 
3
+ class ValidationFailed < StandardError
4
+ attr_reader :errors
5
+
6
+ def initialize(errors)
7
+ super("validation failed with #{errors.size} errors")
8
+ @errors = errors
9
+ end
10
+ end
11
+
12
+ class Error
13
+ attr_reader :options
14
+
15
+ def initialize(options={})
16
+ @options = options
17
+ end
18
+ end
19
+
3
20
  class Scope
4
21
  def value
5
22
  Value.new
@@ -19,8 +36,10 @@ class Valuedate
19
36
  end
20
37
  end
21
38
 
39
+ attr_reader :errors
22
40
 
23
41
  def initialize(&block)
42
+ @errors = []
24
43
  @validators = []
25
44
  if block
26
45
  validator = Scope.new.instance_eval(&block)
@@ -32,13 +51,18 @@ class Valuedate
32
51
  valid? do |value|
33
52
  value ||= {}
34
53
  schema.all? do |(key, validator)|
35
- validator.validate(value[key])
54
+ validator.call(value[key]) || collect_errors!(validator, :key => key)
36
55
  end
37
56
  end
38
57
  end
39
58
 
40
59
  def validate(value = nil)
41
- @validators.all? { |validator| validator.call(value) }
60
+ @errors.clear
61
+ @validators.all? { |validator| validator.call(value) || collect_errors!(validator) }
62
+ end
63
+
64
+ def validate!(value = nil)
65
+ validate(value) or raise ValidationFailed.new(@errors)
42
66
  end
43
67
 
44
68
  def call(value)
@@ -50,9 +74,28 @@ class Valuedate
50
74
  self
51
75
  end
52
76
 
77
+ def collect_errors!(validator, options = {})
78
+ case validator
79
+ when Valuedate
80
+ @errors.concat(validator.errors.map { |error| error.options.update(options); error })
81
+ end
82
+ false
83
+ end
84
+
85
+ def errors
86
+ @errors.uniq
87
+ end
88
+
89
+ def error(options={})
90
+ @errors << Error.new(options)
91
+ false
92
+ end
93
+
53
94
  def method_missing(method, *args, &block)
54
95
  if matcher = Valuedate.matchers[method]
55
- valid? { |value| matcher.call(value, *args, &block) }
96
+ valid? do |value|
97
+ matcher.call(value, *args, &block) || error(:matcher => method, :value => value, :args => args)
98
+ end
56
99
  else
57
100
  super
58
101
  end
@@ -6,6 +6,22 @@ class Riot::Situation
6
6
  end
7
7
  end
8
8
 
9
+ class Riot::Context
10
+ def asserts_validation_error(options={}, &block)
11
+ asserts("validation_error with #{options.inspect}") do
12
+ begin
13
+ instance_eval(&block)
14
+ false
15
+ rescue Valuedate::ValidationFailed => e
16
+ error = e.errors.first
17
+ options.all? do |key, value|
18
+ error.options[key] == value
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
9
25
  context "Valuedate" do
10
26
 
11
27
  asserts(:class) { Valuedate.schema }.equals(Valuedate)
@@ -179,4 +195,38 @@ context "Valuedate" do
179
195
  asserts("valid array size") { v([1,2]) { value.is { |value| value.size == 2 } } }
180
196
  asserts("invalid array size") { !v([1,2]) { value.not { |value| value.size == 2 } } }
181
197
  end
198
+
199
+ context "errors" do
200
+ setup do
201
+ Valuedate.schema {}
202
+ end
203
+
204
+ asserts("empty") { topic.errors.empty? }
205
+ asserts("with error") do
206
+ topic.error(:value => "value")
207
+ topic.errors.first.options[:value]
208
+ end.equals("value")
209
+
210
+ context "aggregate" do
211
+ setup do
212
+ Valuedate.schema do
213
+ value.hash(
214
+ :key1 => value.is_a(String).equals("key"),
215
+ :key2 => value.hash(
216
+ :key3 => value.is_a(Fixnum)
217
+ )
218
+ )
219
+ end
220
+ end
221
+
222
+ asserts("fails") { !topic.validate({}) }
223
+ asserts_validation_error(:key => :key1, :matcher => :is_a) { topic.validate!({}) }
224
+ asserts_validation_error(:key => :key1, :matcher => :is_a) { topic.validate!(:key1 => 23) }
225
+ asserts_validation_error(:key => :key1, :matcher => :equals) { topic.validate!(:key1 => "value") }
226
+ asserts_validation_error(:key => :key2, :matcher => :is_a) { topic.validate!(:key1 => "key") }
227
+ asserts_validation_error(:key => :key2, :matcher => :is_a) { topic.validate!(:key1 => "key", :key2 => {}) }
228
+ asserts_validation_error(:key => :key2, :matcher => :is_a) { topic.validate!(:key1 => "key", :key2 => {:key3 => 0.0}) }
229
+ asserts("passes") { topic.validate(:key1 => "key", :key2 => {:key3 => 23}) }
230
+ end
231
+ end
182
232
  end
data/valuedate.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{valuedate}
8
- s.version = "0.0.3"
8
+ s.version = "0.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Peter Suschlik"]
12
- s.date = %q{2010-01-28}
12
+ s.date = %q{2010-01-30}
13
13
  s.email = %q{peter-valuedate@suschlik.de}
14
14
  s.extra_rdoc_files = [
15
15
  "README.rdoc"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valuedate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Suschlik
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-28 00:00:00 +01:00
12
+ date: 2010-01-30 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency