ratatouille 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis-yml +2 -2
- data/README.md +4 -1
- data/lib/ratatouille/array.rb +10 -4
- data/lib/ratatouille/hash.rb +44 -10
- data/lib/ratatouille/ratifier.rb +26 -3
- data/lib/ratatouille/version.rb +1 -1
- data/lib/ratatouille.rb +3 -2
- data/spec/lib/ratatouille/hash_spec.rb +46 -2
- data/spec/lib/ratatouille/ratifier_spec.rb +30 -0
- metadata +3 -4
- data/.rvmrc +0 -1
data/.gitignore
CHANGED
data/.travis-yml
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
# Ratatouille
|
1
|
+
# Ratatouille
|
2
2
|
|
3
3
|
DSL for validation of complex Hashes
|
4
4
|
|
5
|
+
## Travis CI Status:
|
6
|
+
[![Build Status](https://secure.travis-ci.org/CITguy/ratatouille.png?branch=master)](http://travis-ci.org/CITguy/ratatouille)
|
7
|
+
|
5
8
|
## Installation
|
6
9
|
|
7
10
|
Add this line to your application's Gemfile:
|
data/lib/ratatouille/array.rb
CHANGED
@@ -5,22 +5,26 @@ module Ratatouille
|
|
5
5
|
# @return [void]
|
6
6
|
def is_empty(&block)
|
7
7
|
unless @ratifiable_object.empty?
|
8
|
-
validation_error("
|
8
|
+
validation_error("not empty")
|
9
9
|
return
|
10
10
|
end
|
11
11
|
|
12
12
|
instance_eval(&block) if block_given?
|
13
|
+
rescue Exception => e
|
14
|
+
validation_error("#{e.message}")
|
13
15
|
end#is_empty
|
14
16
|
|
15
17
|
|
16
18
|
# @return [void]
|
17
19
|
def is_not_empty(&block)
|
18
20
|
if @ratifiable_object.empty?
|
19
|
-
validation_error("
|
21
|
+
validation_error("empty")
|
20
22
|
return
|
21
23
|
end
|
22
24
|
|
23
25
|
instance_eval(&block) if block_given?
|
26
|
+
rescue Exception => e
|
27
|
+
validation_error("#{e.message}")
|
24
28
|
end#is_not_empty
|
25
29
|
|
26
30
|
|
@@ -78,6 +82,8 @@ module Ratatouille
|
|
78
82
|
end
|
79
83
|
|
80
84
|
instance_eval(&block) if block_given?
|
85
|
+
rescue Exception => e
|
86
|
+
validation_error("#{e.message}")
|
81
87
|
end#length_between
|
82
88
|
private
|
83
89
|
|
@@ -89,7 +95,7 @@ module Ratatouille
|
|
89
95
|
end
|
90
96
|
|
91
97
|
unless @ratifiable_object.size >= min_size.to_i
|
92
|
-
validation_error("
|
98
|
+
validation_error("length must be #{min_size} or more")
|
93
99
|
return false
|
94
100
|
end
|
95
101
|
return true
|
@@ -106,7 +112,7 @@ module Ratatouille
|
|
106
112
|
end
|
107
113
|
|
108
114
|
if @ratifiable_object.size > max_size.to_i
|
109
|
-
validation_error("
|
115
|
+
validation_error("length must be less than #{max_size.to_i}")
|
110
116
|
return false
|
111
117
|
end
|
112
118
|
|
data/lib/ratatouille/hash.rb
CHANGED
@@ -5,33 +5,42 @@ module Ratatouille
|
|
5
5
|
# Runs validation in block against object for the given key.
|
6
6
|
#
|
7
7
|
# @param [String, Symbol] key
|
8
|
-
|
8
|
+
# @param [Hash] options
|
9
|
+
def given_key(key, options={}, &block)
|
10
|
+
options[:name] = options.fetch(:name, (Symbol === key ? ":#{key}" : key.to_s) )
|
11
|
+
|
9
12
|
if @ratifiable_object.has_key?(key) && block_given?
|
10
|
-
child_object = Ratatouille::Ratifier.new(@ratifiable_object[key], &block)
|
13
|
+
child_object = Ratatouille::Ratifier.new(@ratifiable_object[key], options, &block)
|
11
14
|
@errors[key] = child_object.errors unless child_object.valid?
|
12
15
|
end
|
16
|
+
rescue Exception => e
|
17
|
+
validation_error("#{e.message}")
|
13
18
|
end#given_key
|
14
19
|
|
15
20
|
|
16
21
|
# @return [void]
|
17
22
|
def is_empty(&block)
|
18
23
|
unless @ratifiable_object.empty?
|
19
|
-
validation_error("
|
24
|
+
validation_error("not empty")
|
20
25
|
return
|
21
26
|
end
|
22
27
|
|
23
28
|
instance_eval(&block) if block_given?
|
29
|
+
rescue Exception => e
|
30
|
+
validation_error("#{e.message}")
|
24
31
|
end#is_empty
|
25
32
|
|
26
33
|
|
27
34
|
# @return [void]
|
28
35
|
def is_not_empty(&block)
|
29
36
|
if @ratifiable_object.empty?
|
30
|
-
validation_error("
|
37
|
+
validation_error("empty")
|
31
38
|
return
|
32
39
|
end
|
33
40
|
|
34
41
|
instance_eval(&block) if block_given?
|
42
|
+
rescue Exception => e
|
43
|
+
validation_error("#{e.message}")
|
35
44
|
end#is_not_empty
|
36
45
|
|
37
46
|
|
@@ -44,12 +53,12 @@ module Ratatouille
|
|
44
53
|
common_keys = (@ratifiable_object.keys & req_keys)
|
45
54
|
|
46
55
|
if @ratifiable_object.empty?
|
47
|
-
validation_error("Cannot find required keys
|
56
|
+
validation_error("Cannot find required keys")
|
48
57
|
return
|
49
58
|
end
|
50
59
|
|
51
60
|
if req_keys.nil? || req_keys.empty?
|
52
|
-
validation_error("No required keys given to compare
|
61
|
+
validation_error("No required keys given to compare against.")
|
53
62
|
return
|
54
63
|
end
|
55
64
|
|
@@ -66,6 +75,8 @@ module Ratatouille
|
|
66
75
|
end
|
67
76
|
|
68
77
|
instance_eval(&block) if block_given?
|
78
|
+
rescue Exception => e
|
79
|
+
validation_error("#{e.message}")
|
69
80
|
end#required_keys
|
70
81
|
|
71
82
|
|
@@ -79,13 +90,29 @@ module Ratatouille
|
|
79
90
|
# All other values are ignored.
|
80
91
|
# @return [void]
|
81
92
|
def choice_of(choice_size=1, *key_list, &block)
|
82
|
-
|
93
|
+
if key_list.nil? || key_list.empty?
|
83
94
|
validation_error("choice_of requires a key list to choose from")
|
84
95
|
return
|
85
96
|
end
|
97
|
+
key_list.flatten!
|
98
|
+
|
99
|
+
# I can work with a non-zero integer or any object that responds
|
100
|
+
case choice_size
|
101
|
+
when Integer
|
102
|
+
unless choice_size > 0
|
103
|
+
validation_error("choice_of requires a positive integer for choice size")
|
104
|
+
return
|
105
|
+
end
|
106
|
+
else
|
107
|
+
unless choice_size.respond_to?(:to_i)
|
108
|
+
validation_error("choice_of requires an object that responds to :to_i for choice size")
|
109
|
+
return
|
110
|
+
end
|
111
|
+
choice_size = choice_size.to_i
|
112
|
+
end
|
86
113
|
|
87
|
-
unless choice_size
|
88
|
-
validation_error("choice_of
|
114
|
+
unless choice_size > 0
|
115
|
+
validation_error("choice size for choice_of must be positive non-zero number")
|
89
116
|
return
|
90
117
|
end
|
91
118
|
|
@@ -96,12 +123,19 @@ module Ratatouille
|
|
96
123
|
|
97
124
|
common_keys = (@ratifiable_object.keys & key_list)
|
98
125
|
unless common_keys.size == choice_size
|
99
|
-
choices = key_list.collect{|a|
|
126
|
+
choices = key_list.collect{|a|
|
127
|
+
case a
|
128
|
+
when Symbol then ":#{a}"
|
129
|
+
when String then "#{a}"
|
130
|
+
end
|
131
|
+
}
|
100
132
|
validation_error("Require #{choice_size} of the following: #{choices.join(', ')}")
|
101
133
|
return
|
102
134
|
end
|
103
135
|
|
104
136
|
instance_eval(&block) if block_given?
|
137
|
+
rescue Exception => e
|
138
|
+
validation_error("#{e.message}")
|
105
139
|
end#choice_of
|
106
140
|
end#HashMethods
|
107
141
|
|
data/lib/ratatouille/ratifier.rb
CHANGED
@@ -7,9 +7,11 @@ module Ratatouille
|
|
7
7
|
|
8
8
|
# A new instance of Ratifier
|
9
9
|
# @param [Hash, Array] obj Object to validate
|
10
|
+
# @param [Hash] options
|
10
11
|
def initialize(obj, options={}, &block)
|
11
12
|
@errors = { "/" => [] }
|
12
13
|
@ratifiable_object = obj
|
14
|
+
self.name = options[:name]
|
13
15
|
|
14
16
|
case obj
|
15
17
|
when Hash then extend Ratatouille::HashMethods
|
@@ -24,6 +26,27 @@ module Ratatouille
|
|
24
26
|
end#initialize
|
25
27
|
|
26
28
|
|
29
|
+
# Name of instance
|
30
|
+
#
|
31
|
+
# @return [String]
|
32
|
+
def name
|
33
|
+
@name ||= @ratifiable_object.class.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# Set name of instance
|
38
|
+
#
|
39
|
+
# @param [String] namein
|
40
|
+
# @return [String] name of Ratatouille::Ratifier instance
|
41
|
+
def name=(namein)
|
42
|
+
case namein
|
43
|
+
when String
|
44
|
+
@name = namein unless namein.blank?
|
45
|
+
end
|
46
|
+
@name
|
47
|
+
end
|
48
|
+
|
49
|
+
|
27
50
|
# Add validation error. Useful for custom validations.
|
28
51
|
# @param [String] str
|
29
52
|
# @param [String] context
|
@@ -33,10 +56,10 @@ module Ratatouille
|
|
33
56
|
when String
|
34
57
|
return if err_in.blank?
|
35
58
|
@errors[context] = [] unless @errors[context]
|
36
|
-
@errors[context] << err_in
|
59
|
+
@errors[context] << "#{@name}: #{err_in}"
|
37
60
|
end
|
38
61
|
rescue Exception => e
|
39
|
-
@errors["/"] << e.message
|
62
|
+
@errors["/"] << "#{@name}: #{e.message}"
|
40
63
|
end#validation_error
|
41
64
|
|
42
65
|
|
@@ -54,7 +77,7 @@ module Ratatouille
|
|
54
77
|
def cleanup_errors
|
55
78
|
@errors = {} if errors_array.empty?
|
56
79
|
rescue Exception => e
|
57
|
-
|
80
|
+
validation_error("#{e.message}", '/')
|
58
81
|
end#cleanup_errors
|
59
82
|
|
60
83
|
|
data/lib/ratatouille/version.rb
CHANGED
data/lib/ratatouille.rb
CHANGED
@@ -10,9 +10,10 @@ require "ratatouille/string"
|
|
10
10
|
module Ratatouille
|
11
11
|
|
12
12
|
# @param [Hash, Array] obj Object to validate
|
13
|
+
# @param [Hash] options
|
13
14
|
# @return [Validatable::Ratifier]
|
14
|
-
def ratify(obj, &block)
|
15
|
-
Ratatouille::Ratifier.new(obj, &block)
|
15
|
+
def ratify(obj, options={}, &block)
|
16
|
+
Ratatouille::Ratifier.new(obj, options, &block)
|
16
17
|
end#ratify
|
17
18
|
|
18
19
|
end
|
@@ -33,14 +33,28 @@ describe "Ratatouille::HashMethods" do
|
|
33
33
|
it "should be invalid if choice list is not 1 more than choice size" do
|
34
34
|
RatifierTest.new({}) { choice_of(1, [:foo]) }.should_not be_valid
|
35
35
|
end
|
36
|
+
|
37
|
+
it "should be valid when given hash has 1 key in a choice list of 2 or more" do
|
38
|
+
RatifierTest.new({:foo => "bar"}){ choice_of(1, [:foo, :bar]) }.should be_valid
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be valid when given hash has 2 keys in choice list of 3 or more" do
|
42
|
+
RatifierTest.new({:foo => "foo", :bar => "bar"}){
|
43
|
+
choice_of(2, [:foo, :bar, :biz])
|
44
|
+
}.should be_valid
|
45
|
+
|
46
|
+
RatifierTest.new({:foo => "foo", :bar => "bar"}){
|
47
|
+
choice_of(2, [:foo, :bar, :biz, :bang])
|
48
|
+
}.should be_valid
|
49
|
+
end
|
36
50
|
end
|
37
51
|
|
38
52
|
describe "required_keys" do
|
39
|
-
it "should be valid if
|
53
|
+
it "should be valid if Hash contains all required keys" do
|
40
54
|
RatifierTest.new({:foo => "foo"}) { required_keys(:foo, :bar) }.should_not be_valid
|
41
55
|
end
|
42
56
|
|
43
|
-
it "should be invalid if
|
57
|
+
it "should be invalid if Hash is empty and key list is not" do
|
44
58
|
RatifierTest.new({}) { required_keys(:foo) }.should_not be_valid
|
45
59
|
end
|
46
60
|
|
@@ -48,4 +62,34 @@ describe "Ratatouille::HashMethods" do
|
|
48
62
|
RatifierTest.new({:foo => "foo"}) { required_keys(:foo, :bar) }.should_not be_valid
|
49
63
|
end
|
50
64
|
end
|
65
|
+
|
66
|
+
describe "given_key" do
|
67
|
+
it "should change the scope name to default to the key if no name passed as option" do
|
68
|
+
n = ""
|
69
|
+
RatifierTest.new({:foo => "bar"}) do
|
70
|
+
given_key(:foo) { n = name }
|
71
|
+
end
|
72
|
+
n.should == ":foo"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should change the scope name when passed as an option" do
|
76
|
+
o = n = ""
|
77
|
+
RatifierTest.new({:foo => "bar"}, :name => "Outer") do
|
78
|
+
o = name
|
79
|
+
given_key(:foo, :name => "None") { n = name }
|
80
|
+
end
|
81
|
+
o.should == "Outer"
|
82
|
+
n.should == "None"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not change the outer scope's name" do
|
86
|
+
o = n = ""
|
87
|
+
RatifierTest.new({:foo => "bar"}) do
|
88
|
+
given_key(:foo) { n = name }
|
89
|
+
o = name
|
90
|
+
end
|
91
|
+
o.should == "Hash"
|
92
|
+
n.should == ":foo"
|
93
|
+
end
|
94
|
+
end
|
51
95
|
end
|
@@ -120,4 +120,34 @@ describe Ratatouille::Ratifier do
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
123
|
+
|
124
|
+
describe "name" do
|
125
|
+
it "should return the same value if called twice in a row" do
|
126
|
+
r = RatifierTest.new({})
|
127
|
+
r.name.should == r.name
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should always return a String" do
|
131
|
+
RatifierTest.new({}).name.should be_a String
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should return the class of the object if :name isn't passed into options" do
|
135
|
+
RatifierTest.new({}).name.should == "Hash"
|
136
|
+
RatifierTest.new(Object.new).name.should == "Object"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should return the name as passed into options of new instance" do
|
140
|
+
RatifierTest.new({}, :name => "Foo").name.should == "Foo"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "name=" do
|
145
|
+
it "should not change the name if passed a non-string name" do
|
146
|
+
r = RatifierTest.new({})
|
147
|
+
r.name = NilClass
|
148
|
+
r.name = Object.new
|
149
|
+
r.name = nil
|
150
|
+
r.name.should == 'Hash'
|
151
|
+
end
|
152
|
+
end
|
123
153
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ratatouille
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 2
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Johnson
|
@@ -58,7 +58,6 @@ extra_rdoc_files: []
|
|
58
58
|
|
59
59
|
files:
|
60
60
|
- .gitignore
|
61
|
-
- .rvmrc
|
62
61
|
- .travis-yml
|
63
62
|
- .yardopts
|
64
63
|
- Gemfile
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm --create use 1.8.7@ratatouille
|