valuedate 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/README.rdoc +61 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/lib/valuedate.rb +86 -0
- data/test.watchr +20 -0
- data/test/helper.rb +7 -0
- data/test/test_valuedate.rb +172 -0
- metadata +81 -0
data/.gitignore
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
= Valuedate
|
2
|
+
|
3
|
+
Validates values using a schema.
|
4
|
+
|
5
|
+
Source[http://github.com/splattael/valuedate] | RDoc[http://rdoc.info/projects/splattael/valuedate] | Metrics[http://getcaliper.com/caliper/project?repo=git%3A%2F%2Fgithub.com%2Fsplattael%2Fvaluedate.git]
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
schema = Valuedate.schema do
|
10
|
+
value.is_a(String).equals("test")
|
11
|
+
end
|
12
|
+
|
13
|
+
schema.validate("test") # => true
|
14
|
+
schema.validate("fail") # => false
|
15
|
+
schema.validate(23) # => false
|
16
|
+
|
17
|
+
deep = Valuedate.schema do
|
18
|
+
value.hash(
|
19
|
+
:type => value.is_a(String),
|
20
|
+
:value => value.hash(
|
21
|
+
:src => value.is_a(String),
|
22
|
+
:height => optional_value.is_a(Fixnum),
|
23
|
+
:width => optional_value.is_a(Fixnum)
|
24
|
+
)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
deep.validate(
|
29
|
+
:type => "image",
|
30
|
+
:value => {
|
31
|
+
:src => "/bold.gif",
|
32
|
+
:height => 80,
|
33
|
+
:width => 80
|
34
|
+
}
|
35
|
+
) # => true
|
36
|
+
|
37
|
+
# :height and width are optional
|
38
|
+
deep.validate(:type => "image", :value => { :src => "/bold.gif" }) # => true
|
39
|
+
|
40
|
+
== Matchers
|
41
|
+
|
42
|
+
Following matchers are defined:
|
43
|
+
* is_a(Class)
|
44
|
+
* equals(expected)
|
45
|
+
* any(list of validators)
|
46
|
+
* is(range, array or anything that responds_to #include?)
|
47
|
+
|
48
|
+
== Defining matchers
|
49
|
+
|
50
|
+
Valuedate.matcher(:equals) { |value, expected| value == expected }
|
51
|
+
|
52
|
+
== Install
|
53
|
+
|
54
|
+
git clone ...
|
55
|
+
rake install
|
56
|
+
|
57
|
+
== Authors
|
58
|
+
* Peter Suschlik
|
59
|
+
|
60
|
+
== TODO
|
61
|
+
* Implement and aggregate errors
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gem|
|
6
|
+
gem.name = "valuedate"
|
7
|
+
gem.summary = 'Validates values.'
|
8
|
+
gem.email = "peter-valuedate@suschlik.de"
|
9
|
+
gem.homepage = "http://github.com/splattael/valuedate"
|
10
|
+
gem.authors = ["Peter Suschlik"]
|
11
|
+
|
12
|
+
gem.has_rdoc = true
|
13
|
+
gem.extra_rdoc_files = [ "README.rdoc" ]
|
14
|
+
|
15
|
+
gem.add_dependency "riot", ">= 0.10.11"
|
16
|
+
gem.add_development_dependency "riot_notifier"
|
17
|
+
|
18
|
+
gem.test_files = Dir.glob('test/test_*.rb')
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Test
|
26
|
+
require 'rake/testtask'
|
27
|
+
desc 'Default: run unit tests.'
|
28
|
+
task :default => :test
|
29
|
+
task :test => :check_dependencies
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |test|
|
32
|
+
test.test_files = FileList.new('test/test_*.rb')
|
33
|
+
test.libs << 'test'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
|
37
|
+
# RDoc
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rd|
|
40
|
+
rd.title = "Valuedate"
|
41
|
+
rd.main = "README.rdoc"
|
42
|
+
rd.rdoc_files.include("README.rdoc", "lib/*.rb")
|
43
|
+
rd.rdoc_dir = "doc"
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Misc
|
48
|
+
desc "Tag files for vim"
|
49
|
+
task :ctags do
|
50
|
+
dirs = $LOAD_PATH.select {|path| File.directory?(path) }
|
51
|
+
system "ctags -R #{dirs.join(" ")}"
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Find whitespace at line ends"
|
55
|
+
task :eol do
|
56
|
+
system "grep -nrE ' +$' *"
|
57
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
data/lib/valuedate.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
class Valuedate
|
2
|
+
|
3
|
+
class Scope
|
4
|
+
def value
|
5
|
+
Value.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def optional_value
|
9
|
+
OptionalValue.new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Value < Valuedate
|
14
|
+
end
|
15
|
+
|
16
|
+
class OptionalValue < Valuedate
|
17
|
+
def validate(value = nil)
|
18
|
+
value.nil? || super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def initialize(&block)
|
24
|
+
@validators = []
|
25
|
+
if block
|
26
|
+
validator = Scope.new.instance_eval(&block)
|
27
|
+
@validators << validator if validator.respond_to?(:call)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def hash(schema={})
|
32
|
+
valid? do |value|
|
33
|
+
value ||= {}
|
34
|
+
schema.all? do |(key, validator)|
|
35
|
+
validator.validate(value[key])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate(value = nil)
|
41
|
+
@validators.all? { |validator| validator.call(value) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def call(value)
|
45
|
+
validate(value)
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid?(&block)
|
49
|
+
@validators << block
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(method, *args, &block)
|
54
|
+
if matcher = Valuedate.matchers[method]
|
55
|
+
valid? { |value| matcher.call(value, *args) }
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@matchers = {}
|
62
|
+
class << self
|
63
|
+
attr_reader :matchers
|
64
|
+
|
65
|
+
def validate(value, &block)
|
66
|
+
schema(&block).validate(value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def schema(&block)
|
70
|
+
new(&block)
|
71
|
+
end
|
72
|
+
|
73
|
+
def matcher(name, &block)
|
74
|
+
undef_method(name) if respond_to?(name)
|
75
|
+
@matchers[name] = block
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
Valuedate.matcher(:equals) { |value, expected| value == expected }
|
82
|
+
Valuedate.matcher(:is_a) { |value, expected| value.is_a?(expected) }
|
83
|
+
Valuedate.matcher(:any) do |value, *validators|
|
84
|
+
validators.any? { |validator| validator.validate(value) }
|
85
|
+
end
|
86
|
+
Valuedate.matcher(:in) { |value, expected| expected.include?(value) }
|
data/test.watchr
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env watchr
|
2
|
+
|
3
|
+
begin
|
4
|
+
require File.join(ENV["HOME"], ".watchr.test.rb")
|
5
|
+
rescue LoadError
|
6
|
+
warn "Unable to load #{File.join(ENV["HOME"], ".watchr.test.rb")}"
|
7
|
+
warn "You might try this: http://gist.github.com/raw/273574/8804dff44b104e9b8706826dc8882ed985b4fd13/.watchr.test.rb"
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
|
11
|
+
run_tests
|
12
|
+
|
13
|
+
watch('test/test_.*\.rb') {|md| run md[0] }
|
14
|
+
watch('lib/(.*)\.rb') {|md| run "test/test_#{underscore(md[1])}.rb" }
|
15
|
+
watch('test/helper.rb') { run_tests }
|
16
|
+
|
17
|
+
watch('VERSION') do
|
18
|
+
puts "Building gem"
|
19
|
+
system "rake build"
|
20
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class Riot::Situation
|
4
|
+
def v(value=nil, &block)
|
5
|
+
Valuedate.validate(value, &block)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
context "Valuedate" do
|
10
|
+
|
11
|
+
asserts(:class) { Valuedate.schema }.equals(Valuedate)
|
12
|
+
|
13
|
+
context "empty" do
|
14
|
+
asserts("valid without block") { v }
|
15
|
+
asserts("valid empty block") { v {} }
|
16
|
+
asserts("valid nil block") { v { nil } }
|
17
|
+
asserts("valid nil") { v(nil) }
|
18
|
+
asserts("valid 1") { v(1) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "callable" do
|
22
|
+
asserts("valid with true") { v { proc {|v| true } } }
|
23
|
+
asserts("invalid with false") { !v { proc {|v| false } } }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "matchers" do
|
27
|
+
asserts("equals") { Valuedate.matchers[:equals].call(1, 1) }
|
28
|
+
asserts("!equals") { !Valuedate.matchers[:equals].call(1, 2) }
|
29
|
+
asserts("is_a") { Valuedate.matchers[:is_a].call("string", String) }
|
30
|
+
asserts("!is_a") { !Valuedate.matchers[:is_a].call("string", Fixnum) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "equals" do
|
34
|
+
asserts("valid 1") { v(1) { value.equals 1 } }
|
35
|
+
asserts("invalid 2") { !v(2) { value.equals 1 } }
|
36
|
+
asserts("valid String") { v("test") { value.equals "test" } }
|
37
|
+
asserts("invalid String") { !v("test") { value.equals "tests" } }
|
38
|
+
asserts("invalid multiple") { !v(1) { value.equals 1; value.equals 2} }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "is_a" do
|
42
|
+
asserts("valid String") { v("test") { value.is_a(String) } }
|
43
|
+
asserts("invalid String") { !v(1) { value.is_a(String) } }
|
44
|
+
asserts("valid multiple") { v("test") { value.is_a(String); value.is_a(Object) } }
|
45
|
+
asserts("invalid multiple") { !v("test") { value.is_a(String); value.is_a(Fixnum) } }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "chaining" do
|
49
|
+
asserts("valid") { v(1) { value.is_a(Fixnum).equals(1) }}
|
50
|
+
asserts("invalid") { !v(1) { value.is_a(Fixnum).equals(2) }}
|
51
|
+
end
|
52
|
+
|
53
|
+
context "nesting" do
|
54
|
+
setup do
|
55
|
+
Valuedate.schema do
|
56
|
+
value.hash(
|
57
|
+
:key => value.is_a(String),
|
58
|
+
:value => value.is_a(Fixnum)
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
asserts("valid") { topic.validate(:key => "fasel", :value => 23) }
|
64
|
+
asserts("invalid") { !topic.validate(:key => 23, :value => 23) }
|
65
|
+
asserts("missing") { !topic.validate(:key => "fasel") }
|
66
|
+
end
|
67
|
+
|
68
|
+
context "deep nesting" do
|
69
|
+
setup do
|
70
|
+
Valuedate.schema do
|
71
|
+
value.hash(
|
72
|
+
:image => value.hash(
|
73
|
+
:src => value.is_a(String),
|
74
|
+
:height => value.is_a(Fixnum)
|
75
|
+
),
|
76
|
+
:text => value.is_a(String)
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
asserts("valid") do
|
82
|
+
topic.validate(
|
83
|
+
:image => {
|
84
|
+
:src => "/image.gif",
|
85
|
+
:height => 80
|
86
|
+
},
|
87
|
+
:text => "Image"
|
88
|
+
)
|
89
|
+
end
|
90
|
+
asserts("invalid") do
|
91
|
+
!topic.validate(
|
92
|
+
:image => {
|
93
|
+
:src => "/image.gif",
|
94
|
+
},
|
95
|
+
:text => "Image"
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
end # deep nesting
|
100
|
+
|
101
|
+
context "optional_value" do
|
102
|
+
asserts("valid nil") { v(nil) { optional_value } }
|
103
|
+
asserts("valid 1") { v(1) { optional_value } }
|
104
|
+
asserts("valid empty optional String") { v(nil) { optional_value.is_a(String) } }
|
105
|
+
asserts("valid given and String") { v("test") { optional_value.is_a(String) } }
|
106
|
+
asserts("invalid given non-String") { !v(1) { optional_value.is_a(String) } }
|
107
|
+
|
108
|
+
context "netsted" do
|
109
|
+
setup do
|
110
|
+
Valuedate.schema do
|
111
|
+
optional_value.hash(
|
112
|
+
:image => value.hash(
|
113
|
+
:src => value.is_a(String),
|
114
|
+
:alt => optional_value.is_a(String),
|
115
|
+
:size => optional_value.hash(
|
116
|
+
:width => value.is_a(Fixnum),
|
117
|
+
:height => value.is_a(Fixnum)
|
118
|
+
)
|
119
|
+
)
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
asserts("valid empty") { topic.validate }
|
125
|
+
asserts("invalid non Hash") { !topic.validate(23) }
|
126
|
+
asserts("invalid wrong key") { !topic.validate(:type => {}) }
|
127
|
+
asserts("invalid empty image") { !topic.validate(:image => {}) }
|
128
|
+
asserts("valid all given") do
|
129
|
+
topic.validate(
|
130
|
+
:image => {
|
131
|
+
:src => "/img.gif",
|
132
|
+
:alt => "Alt",
|
133
|
+
:size => { :width => 80, :height => 80 }
|
134
|
+
}
|
135
|
+
)
|
136
|
+
end
|
137
|
+
asserts("valid minimal Hash") { topic.validate(:image => { :src => "/img.gif" }) }
|
138
|
+
asserts("invalid alt") { !topic.validate(:image => { :src => "/img.gif", :alt => 23 }) }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "any" do
|
143
|
+
asserts("valid") { v(1) { value.any(value.equals(1), value.equals(2)) } }
|
144
|
+
asserts("valid") { v(2) { value.any(value.equals(1), value.equals(2)) } }
|
145
|
+
asserts("invalid") { !v(3) { value.any(value.equals(1), value.equals(2)) } }
|
146
|
+
|
147
|
+
context "nested" do
|
148
|
+
setup do
|
149
|
+
Valuedate.schema do
|
150
|
+
value.any(
|
151
|
+
value.hash(:result => value.equals("ok")),
|
152
|
+
value.hash(:error => value.equals("failed"), :init => value.equals(23))
|
153
|
+
)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
asserts("invalid when empty") { !topic.validate }
|
158
|
+
asserts("valid when result ok") { topic.validate(:result => "ok") }
|
159
|
+
asserts("invalid when result nok") { !topic.validate(:result => "nok") }
|
160
|
+
asserts("valid when error") { topic.validate(:error => "failed", :init => 23) }
|
161
|
+
asserts("invalid missing init") { !topic.validate(:error => "failed") }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "in" do
|
166
|
+
asserts("valid range") { v(1) { value.in(1..5) } }
|
167
|
+
asserts("invalid range") { !v(0) { value.in(1..5) } }
|
168
|
+
asserts("valid array") { v(1) { value.in([1,2,3]) } }
|
169
|
+
asserts("invalid array") { !v(0) { value.in([1,2,3]) } }
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: valuedate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Suschlik
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-28 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: riot
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.11
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: riot_notifier
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description:
|
36
|
+
email: peter-valuedate@suschlik.de
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.rdoc
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- README.rdoc
|
46
|
+
- Rakefile
|
47
|
+
- VERSION
|
48
|
+
- lib/valuedate.rb
|
49
|
+
- test.watchr
|
50
|
+
- test/helper.rb
|
51
|
+
- test/test_valuedate.rb
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/splattael/valuedate
|
54
|
+
licenses: []
|
55
|
+
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --charset=UTF-8
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Validates values.
|
80
|
+
test_files:
|
81
|
+
- test/test_valuedate.rb
|