ratatouille 1.3.0 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +10 -0
- data/lib/ratatouille/array.rb +9 -44
- data/lib/ratatouille/hash.rb +45 -68
- data/lib/ratatouille/ratifier.rb +49 -0
- data/lib/ratatouille/version.rb +1 -1
- data/spec/lib/ratatouille/array_spec.rb +1 -3
- data/spec/lib/ratatouille/hash_spec.rb +60 -28
- data/spec/lib/ratatouille/ratifier_spec.rb +32 -0
- data/spec/spec_helper.rb +1 -0
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.3.2
|
2
|
+
|
3
|
+
### Updates
|
4
|
+
|
5
|
+
* is\_empty and is\_not\_empty have been moved to generic ghost methods in the Ratifier object that also support other boolean methods.
|
6
|
+
* Say you have Object#foo?, you can use **is\_foo** and **is\_not\_foo** for validation against that boolean method
|
7
|
+
* **:is\_a** added as option to perform class validation prior to the core method logic for the following methods:
|
8
|
+
* HashMethod#given_key
|
9
|
+
* HashMethod#required_key
|
10
|
+
|
1
11
|
## 1.3.0 (API Change!)
|
2
12
|
|
3
13
|
### Updates
|
data/lib/ratatouille/array.rb
CHANGED
@@ -2,47 +2,6 @@ module Ratatouille
|
|
2
2
|
|
3
3
|
# Module used to provide Array-specific validation methods
|
4
4
|
module ArrayMethods
|
5
|
-
|
6
|
-
# @param [Hash] options
|
7
|
-
# @option options [Boolean] :unwrap_block (false)
|
8
|
-
# Perform block validation only -- skip is_empty validation logic.
|
9
|
-
# Useless unless block provided
|
10
|
-
# @return [void]
|
11
|
-
def is_empty(options={}, &block)
|
12
|
-
unless options.fetch(:unwrap_block, false) == true
|
13
|
-
# Wrapped Validation
|
14
|
-
unless @ratifiable_object.empty?
|
15
|
-
validation_error("not empty")
|
16
|
-
return
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
instance_eval(&block) if block_given?
|
21
|
-
rescue Exception => e
|
22
|
-
validation_error("#{e.message}")
|
23
|
-
end#is_empty
|
24
|
-
|
25
|
-
|
26
|
-
# @param [Hash] options
|
27
|
-
# @option options [Boolean] :unwrap_block (false)
|
28
|
-
# Perform block validation only -- skip is_not_empty validation logic.
|
29
|
-
# Useless unless block provided
|
30
|
-
# @return [void]
|
31
|
-
def is_not_empty(options={}, &block)
|
32
|
-
unless options.fetch(:unwrap_block, false) == true
|
33
|
-
# Wrapped Validation
|
34
|
-
if @ratifiable_object.empty?
|
35
|
-
validation_error("empty")
|
36
|
-
return
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
instance_eval(&block) if block_given?
|
41
|
-
rescue Exception => e
|
42
|
-
validation_error("#{e.message}")
|
43
|
-
end#is_not_empty
|
44
|
-
|
45
|
-
|
46
5
|
# Define Minimum Length of Array
|
47
6
|
#
|
48
7
|
# @param [Integer] min_size
|
@@ -52,7 +11,9 @@ module Ratatouille
|
|
52
11
|
# Useless unless block provided
|
53
12
|
# @return [void]
|
54
13
|
def min_length(min_size=0, options={}, &block)
|
55
|
-
|
14
|
+
parse_options(options)
|
15
|
+
|
16
|
+
unless @unwrap_block == true
|
56
17
|
# Wrapped Validation
|
57
18
|
return unless valid_min_length?(min_size)
|
58
19
|
end
|
@@ -72,7 +33,9 @@ module Ratatouille
|
|
72
33
|
# Useless unless block provided
|
73
34
|
# @return [void]
|
74
35
|
def max_length(max_size=0, options={}, &block)
|
75
|
-
|
36
|
+
parse_options(options)
|
37
|
+
|
38
|
+
unless @unwrap_block == true
|
76
39
|
# Wrapped Validation
|
77
40
|
return unless valid_max_length?(max_size)
|
78
41
|
end
|
@@ -93,7 +56,9 @@ module Ratatouille
|
|
93
56
|
# Useless unless block provided
|
94
57
|
# @return [void]
|
95
58
|
def length_between(min_size=0, max_size=nil, options={}, &block)
|
96
|
-
|
59
|
+
parse_options(options)
|
60
|
+
|
61
|
+
unless @unwrap_block == true
|
97
62
|
# Wrapped Validation
|
98
63
|
return unless valid_min_length?(min_size)
|
99
64
|
|
data/lib/ratatouille/hash.rb
CHANGED
@@ -16,19 +16,22 @@ module Ratatouille
|
|
16
16
|
#
|
17
17
|
# @param [String, Symbol] key
|
18
18
|
# @param [Hash] options
|
19
|
+
# @option options [Class] :is_a (nil)
|
20
|
+
# Used to ensure that the value of the required key is of the given class.
|
21
|
+
# * Performed before all other validation (if defined).
|
22
|
+
# * Validation will be skipped if option not defined.
|
19
23
|
# @option options [String, Symbol] :name (key.to_s)
|
20
24
|
# Name of ratifiable_object for use with validation error messages.
|
21
25
|
# @option options [Boolean] :required (false)
|
22
26
|
# Ensure that ratifiable_object has the given key
|
23
|
-
# @option options [Boolean] :unwrap_block (false)
|
24
|
-
# Perform block validation only -- skip is_empty validation logic.
|
25
|
-
# Useless unless block provided
|
26
27
|
def given_key(key, options={}, &block)
|
27
28
|
options[:name] = options.fetch(:name, (Symbol === key ? ":#{key}" : key.to_s) )
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
parse_options(options)
|
31
|
+
|
32
|
+
unless @unwrap_block == true
|
33
|
+
# WRAPPED VALIDATION
|
34
|
+
if @required == true
|
32
35
|
unless @ratifiable_object.has_key?(key)
|
33
36
|
validation_error("Missing key #{key.inspect}")
|
34
37
|
return
|
@@ -36,57 +39,48 @@ module Ratatouille
|
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
39
|
-
if @ratifiable_object.has_key?(key)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
if @ratifiable_object.has_key?(key)
|
43
|
+
unless @unwrap_block == true
|
44
|
+
# WRAPPED VALIDATION
|
45
|
+
unless @is_a.nil?
|
46
|
+
unless @is_a === @ratifiable_object[key]
|
47
|
+
validation_error("key value is not of type #{@is_a}")
|
48
|
+
return
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
47
52
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# @option options [Boolean] :unwrap_block (false)
|
52
|
-
# Perform block validation only -- skip is_empty validation logic.
|
53
|
-
# Useless unless block provided
|
54
|
-
# @return [void]
|
55
|
-
def is_empty(options={}, &block)
|
56
|
-
unless options.fetch(:unwrap_block, false) == true
|
57
|
-
# Wrapped Validation
|
58
|
-
unless @ratifiable_object.empty?
|
59
|
-
validation_error("not empty")
|
60
|
-
return
|
53
|
+
if block_given?
|
54
|
+
child_object = Ratatouille::Ratifier.new(@ratifiable_object[key], options, &block)
|
55
|
+
@errors[key] = child_object.errors unless child_object.valid?
|
61
56
|
end
|
62
57
|
end
|
63
|
-
|
64
|
-
instance_eval(&block) if block_given?
|
65
58
|
rescue Exception => e
|
66
59
|
validation_error("#{e.message}")
|
67
|
-
end#
|
60
|
+
end#given_key
|
68
61
|
|
69
62
|
|
70
|
-
#
|
63
|
+
# Perform validation on a single key that must be present in the Hash to validate.
|
64
|
+
# Otherwise, an error will be added.
|
71
65
|
#
|
66
|
+
# * Eliminates the need to perform given_key methods within a required_keys block.
|
67
|
+
# * Evaluates an optional block in context of key value (same as given_key)
|
68
|
+
#
|
69
|
+
# @param key Required Key
|
72
70
|
# @param [Hash] options
|
73
|
-
# @option options [
|
74
|
-
#
|
75
|
-
#
|
71
|
+
# @option options [Class] :is_a (nil)
|
72
|
+
# Used to ensure that the value of the required key is of the given class.
|
73
|
+
# * Performed before all other validation (if defined).
|
74
|
+
# * Validation will be skipped if option not defined.
|
75
|
+
# @option options [Boolean] :required (true) Used to call given_key.
|
76
76
|
# @return [void]
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
validation_error("empty")
|
82
|
-
return
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
instance_eval(&block) if block_given?
|
77
|
+
def required_key(key, options={}, &block)
|
78
|
+
options[:required] = true
|
79
|
+
# Pass on processing to given_key with :required => true option
|
80
|
+
given_key(key, options, &block)
|
87
81
|
rescue Exception => e
|
88
82
|
validation_error("#{e.message}")
|
89
|
-
end
|
83
|
+
end
|
90
84
|
|
91
85
|
|
92
86
|
# Provide a list of keys that must be present in the Hash to validate.
|
@@ -110,7 +104,9 @@ module Ratatouille
|
|
110
104
|
# Useless unless block provided
|
111
105
|
# @return [void]
|
112
106
|
def required_keys(options={}, &block)
|
113
|
-
|
107
|
+
parse_options(options)
|
108
|
+
|
109
|
+
unless @unwrap_block == true
|
114
110
|
req_keys = options.fetch(:key_list, [])
|
115
111
|
|
116
112
|
# Wrapped Validation
|
@@ -140,25 +136,6 @@ module Ratatouille
|
|
140
136
|
end#required_keys
|
141
137
|
|
142
138
|
|
143
|
-
# Perform validation on a single key that must be present in the Hash to validate.
|
144
|
-
# Otherwise, an error will be added.
|
145
|
-
#
|
146
|
-
# * Eliminates the need to perform given_key methods within a required_keys block.
|
147
|
-
# * Evaluates an optional block in context of key value (same as given_key)
|
148
|
-
#
|
149
|
-
# @param key Required Key
|
150
|
-
# @param [Hash] options
|
151
|
-
# @option options [Boolean] :required (true) Used to call given_key.
|
152
|
-
# @return [void]
|
153
|
-
def required_key(key, options={}, &block)
|
154
|
-
options[:required] = true
|
155
|
-
# Pass on processing to given_key with :required => true option
|
156
|
-
given_key(key, options, &block)
|
157
|
-
rescue Exception => e
|
158
|
-
validation_error("#{e.message}")
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
139
|
# Provide a list of keys to choose from and a choice size.
|
163
140
|
# When the Hash does not contain at least 'choice_size' keys of the key
|
164
141
|
# list provided, an error will be added.
|
@@ -184,10 +161,10 @@ module Ratatouille
|
|
184
161
|
# Perform block validation only -- skip choice_of validation logic.
|
185
162
|
# Useless unless block provided
|
186
163
|
# @return [void]
|
187
|
-
def choice_of(options, &block)
|
188
|
-
options
|
164
|
+
def choice_of(options={}, &block)
|
165
|
+
parse_options(options)
|
189
166
|
|
190
|
-
unless
|
167
|
+
unless @unwrap_block == true
|
191
168
|
choice_size = options.fetch(:choice_size, 1)
|
192
169
|
key_list = options.fetch(:key_list, [])
|
193
170
|
|
data/lib/ratatouille/ratifier.rb
CHANGED
@@ -140,6 +140,55 @@ module Ratatouille
|
|
140
140
|
rescue Exception => e
|
141
141
|
validation_error("#{e.message}", "/")
|
142
142
|
end#is_a?
|
143
|
+
|
144
|
+
|
145
|
+
# Parse out common options into instance_variables for use within the
|
146
|
+
# validation methods defined in various places.
|
147
|
+
#
|
148
|
+
# @param [Hash] options
|
149
|
+
# @option options [Boolean] :unwrap_block (false)
|
150
|
+
# Perform block validation only -- skip method validation logic.
|
151
|
+
def parse_options(options={})
|
152
|
+
@unwrap_block = options.fetch(:unwrap_block, false)
|
153
|
+
@is_a = options.fetch(:is_a, nil)
|
154
|
+
@required = options.fetch(:required, false)
|
155
|
+
end#parse_options
|
156
|
+
|
157
|
+
|
158
|
+
# Override Method Missing for a Ratifier to generate errors for invalid
|
159
|
+
# methods called on incorrect objects (hash validation on arrays, etc.)
|
160
|
+
# as well as some catch-all methods for boolean validations (is_* and is_not_*)
|
161
|
+
def method_missing(id, *args, &block)
|
162
|
+
should_unwrap = false
|
163
|
+
if args.first.respond_to?(:keys)
|
164
|
+
if args.first.fetch(:unwrap_block, false) == true
|
165
|
+
should_unwrap = true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
case
|
170
|
+
when should_unwrap == true
|
171
|
+
# Perform no validation logic
|
172
|
+
# Skip to block evaluation
|
173
|
+
when id.to_s =~ /^is_not_(.*)$/
|
174
|
+
if @ratifiable_object.respond_to?("#{$1}?")
|
175
|
+
if @ratifiable_object.send("#{$1}?") == true
|
176
|
+
validation_error("is #{$1}")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
when id.to_s =~ /^is_(.*)$/
|
180
|
+
if @ratifiable_object.respond_to?("#{$1}?")
|
181
|
+
if @ratifiable_object.send("#{$1}?") == false
|
182
|
+
validation_error("is not #{$1}")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
else
|
186
|
+
validation_error("#{id} is not supported for the given object (#{@ratifiable_object.class})")
|
187
|
+
end
|
188
|
+
|
189
|
+
instance_eval(&block) if block_given?
|
190
|
+
return
|
191
|
+
end#method_missing
|
143
192
|
end#Ratifier
|
144
193
|
|
145
194
|
end
|
data/lib/ratatouille/version.rb
CHANGED
@@ -1,42 +1,56 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Ratatouille::HashMethods" do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
[ :choice_of,
|
5
|
+
:required_keys,
|
6
|
+
:required_key,
|
7
|
+
:given_key
|
8
|
+
].each do |m|
|
9
|
+
it "block context should respond to #{m}" do
|
10
|
+
r = nil
|
11
|
+
RatifierTest.new({}) { r = self }
|
12
|
+
r.should respond_to m
|
7
13
|
end
|
14
|
+
end
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
16
|
+
describe "(backward compatibility)" do
|
17
|
+
describe "is_empty" do
|
18
|
+
it "should be invalid for non-empty Hash" do
|
19
|
+
RatifierTest.new({:bar => 'biz'}){ is_empty }.should_not be_valid
|
20
|
+
end
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
RatifierTest.new({:bar => 'biz'}){
|
16
|
-
is_empty(:unwrap_block => true) do
|
17
|
-
# Nothing to validate, wrapper ignored.
|
18
|
-
end
|
19
|
-
}.should be_valid
|
22
|
+
it "should be valid for empty Hash" do
|
23
|
+
RatifierTest.new({}){ is_empty }.should be_valid
|
20
24
|
end
|
21
|
-
end
|
22
|
-
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
describe "when :unwrap_block is true" do
|
27
|
+
it "should be valid for non-empty Hash" do
|
28
|
+
RatifierTest.new({:bar => 'biz'}){
|
29
|
+
is_empty(:unwrap_block => true) do
|
30
|
+
# Nothing to validate, wrapper ignored.
|
31
|
+
end
|
32
|
+
}.should be_valid
|
33
|
+
end
|
34
|
+
end
|
27
35
|
end
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
37
|
+
describe "is_not_empty" do
|
38
|
+
it "should be valid for non-empty hash" do
|
39
|
+
RatifierTest.new({:bar => "biz"}){ is_not_empty }.should be_valid
|
40
|
+
end
|
32
41
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
42
|
+
it "should not be valid for empty hash" do
|
43
|
+
RatifierTest.new({}){ is_not_empty }.should_not be_valid
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "when :unwrap_block is true" do
|
47
|
+
it "should be valid for empty hash" do
|
48
|
+
RatifierTest.new({}){
|
49
|
+
is_not_empty(:unwrap_block => true) do
|
50
|
+
# Nothing to validate, wrapper ignored
|
51
|
+
end
|
52
|
+
}.should be_valid
|
53
|
+
end
|
40
54
|
end
|
41
55
|
end
|
42
56
|
end
|
@@ -173,6 +187,24 @@ describe "Ratatouille::HashMethods" do
|
|
173
187
|
}.should be_valid
|
174
188
|
end
|
175
189
|
end
|
190
|
+
|
191
|
+
describe "when :is_a is given" do
|
192
|
+
it "should be valid with matching key value class" do
|
193
|
+
RatifierTest.new({:foo => "bar"}){
|
194
|
+
required_key(:foo, :class => String) do
|
195
|
+
# Nothing to validate, wrapper ignored
|
196
|
+
end
|
197
|
+
}.should be_valid
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should be invalid with non-matching key value class" do
|
201
|
+
RatifierTest.new({:foo => "bar"}){
|
202
|
+
required_key(:foo, :is_a => Hash) do
|
203
|
+
# Nothing to validate, wrapper ignored
|
204
|
+
end
|
205
|
+
}.should_not be_valid
|
206
|
+
end
|
207
|
+
end
|
176
208
|
end
|
177
209
|
|
178
210
|
describe "given_key" do
|
@@ -17,6 +17,20 @@ describe Ratatouille::Ratifier do
|
|
17
17
|
x['/'].should be_empty
|
18
18
|
end
|
19
19
|
|
20
|
+
describe "when attempting to call an undefined method" do
|
21
|
+
it "should be invalid to call required_keys on an Array" do
|
22
|
+
RatifierTest.new([]){
|
23
|
+
required_keys(:key_list => [:foo])
|
24
|
+
}.should_not be_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be invalid to call required_keys on an Object" do
|
28
|
+
RatifierTest.new(Object.new){
|
29
|
+
required_keys(:key_list => [:foo])
|
30
|
+
}.should_not be_valid
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
20
34
|
describe "validation_error" do
|
21
35
|
it "should create an error when called within a Ratifier block" do
|
22
36
|
test = RatifierTest.new(Object.new) do
|
@@ -178,4 +192,22 @@ describe Ratatouille::Ratifier do
|
|
178
192
|
end
|
179
193
|
end
|
180
194
|
end
|
195
|
+
|
196
|
+
describe "method_missing" do
|
197
|
+
describe "for non-standard boolean methods" do
|
198
|
+
it "should render object invalid for given method" do
|
199
|
+
obj = Object.new
|
200
|
+
obj.stub(:foo?).and_return(false)
|
201
|
+
RatifierTest.new(obj) { is_foo }.should_not be_valid
|
202
|
+
RatifierTest.new(obj) { is_not_foo }.should be_valid
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should render object valid for given method" do
|
206
|
+
obj = Object.new
|
207
|
+
obj.stub(:bar?).and_return(true)
|
208
|
+
RatifierTest.new(obj) { is_bar }.should be_valid
|
209
|
+
RatifierTest.new(obj) { is_not_bar }.should_not be_valid
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
181
213
|
end
|
data/spec/spec_helper.rb
CHANGED
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
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 1.3.
|
9
|
+
- 2
|
10
|
+
version: 1.3.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Johnson
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-04-
|
18
|
+
date: 2012-04-23 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|