ratatouille 1.3.0 → 1.3.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/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
|