params-validator 0.1.0
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/.rvmrc +2 -0
- data/Gemfile +9 -0
- data/README.md +99 -0
- data/Rakefile +2 -0
- data/lib/params-validator.rb +9 -0
- data/lib/params_validator/method_validation.rb +69 -0
- data/lib/params_validator/parameter.rb +39 -0
- data/lib/params_validator/request.rb +48 -0
- data/lib/params_validator/valid_params.rb +106 -0
- data/lib/params_validator/validator.rb +132 -0
- data/lib/params_validator/version.rb +8 -0
- data/params-validator.gemspec +23 -0
- data/test/main.rb +39 -0
- data/test/method_validation_spec.rb +49 -0
- data/test/mock/mock_object.rb +34 -0
- data/test/parameter_spec.rb +37 -0
- data/test/project/provisioning/application.rb +31 -0
- data/test/project/provisioning/user_object.rb +20 -0
- data/test/request_spec.rb +79 -0
- data/test/valid_params_spec.rb +99 -0
- data/test/yamock_object.rb +16 -0
- metadata +97 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Introduction
|
2
|
+
|
3
|
+
The aim of params-validator is to allow an easy way to validate the
|
4
|
+
parameters in a method call.
|
5
|
+
|
6
|
+
# Install
|
7
|
+
|
8
|
+
gem install params-validator
|
9
|
+
|
10
|
+
# Requirementes
|
11
|
+
|
12
|
+
# Usage
|
13
|
+
|
14
|
+
* There are three ways of use:
|
15
|
+
|
16
|
+
* Include validation rules inside the object:
|
17
|
+
|
18
|
+
require 'params-validator'
|
19
|
+
class MockObject
|
20
|
+
include ParamsValidator::ValidParams
|
21
|
+
# define two useless methods
|
22
|
+
[:method1, :method2].each{|m|
|
23
|
+
define_method(m) do |*args, &block|
|
24
|
+
puts {:foo => "bar"}
|
25
|
+
true
|
26
|
+
end
|
27
|
+
}
|
28
|
+
# method1 arguments ruleset
|
29
|
+
validate_method(:method1) do
|
30
|
+
level(Fixnum, :optional)
|
31
|
+
end
|
32
|
+
# method2 arguments ruleset
|
33
|
+
validate_method(:method2) do
|
34
|
+
data(String) { |data| !data.nil? and data.length > 0}
|
35
|
+
level(Fixnum, :optional) {|level| level <= 3}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
When calling a specific method, an ArgumentError exception will be raised if at least one parameter is invalid
|
41
|
+
|
42
|
+
obj = MockObject.new
|
43
|
+
obj.method1({:level => "1"}) # This will raise an ArgumentError exception because :level parameter type is invalid
|
44
|
+
obj.method1({:level => 1}) # This will execute successfully the method call
|
45
|
+
obj.method2({:level => 1}) # This will raise an ArgumentError exception because :data parameter is missing
|
46
|
+
|
47
|
+
* Include validation rules outside the object:
|
48
|
+
|
49
|
+
class MockObject
|
50
|
+
include ParamsValidator::ValidParams
|
51
|
+
# define two useless methods
|
52
|
+
[:method1, :method2].each{|m|
|
53
|
+
define_method(m) do |*args, &block|
|
54
|
+
true
|
55
|
+
end
|
56
|
+
}
|
57
|
+
# method1 and method2 should be validated, but no ruleset is defined
|
58
|
+
validate_method [:method1, :method2]
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
Then in a separate file, rulesets must be loaded:
|
63
|
+
|
64
|
+
require 'params-validator'
|
65
|
+
include ParamsValidator::ValidParams
|
66
|
+
# define rulesets
|
67
|
+
rules = <<EOF
|
68
|
+
validation_rule("MockObject::method1") do
|
69
|
+
level(Fixnum, :optional)
|
70
|
+
end
|
71
|
+
validation_rule("MockObject::method2") do
|
72
|
+
data(String) { |data| !data.nil? and data.length > 0}
|
73
|
+
level(Fixnum, :optional) {|level| level <= 3}
|
74
|
+
end
|
75
|
+
EOF
|
76
|
+
# load rulesets in validation framework
|
77
|
+
load_rules(rules)
|
78
|
+
obj = MockObject.new
|
79
|
+
obj.method1({:level => "1"}) # This will raise an ArgumentError exception because :level parameter type is invalid
|
80
|
+
obj.method1({:level => 1}) # This will execute successfully the method call
|
81
|
+
obj.method2({:level => 1}) # This will raise an ArgumentError exception because :data parameter is missing
|
82
|
+
|
83
|
+
|
84
|
+
* Client side validation (kudos to @drslump)
|
85
|
+
|
86
|
+
obj = ParamsValidator::Request.new
|
87
|
+
obj[:data] = "this is a log"
|
88
|
+
obj[:level] = 1
|
89
|
+
ruleset = MockObject.get_rule(:method2)
|
90
|
+
obj.valid?(ruleset) # false
|
91
|
+
begin
|
92
|
+
obj.validate(ruleset)
|
93
|
+
rescue ArgumentError => ae
|
94
|
+
p ae.message # array with validation errors
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
More examples can be found in test folder.
|
99
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'params_validator/parameter'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Juan de Bravo <juandebravo@gmail.com>
|
5
|
+
#
|
6
|
+
module ParamsValidator
|
7
|
+
|
8
|
+
#
|
9
|
+
# This class models the information required to validate
|
10
|
+
# a specific method call
|
11
|
+
#
|
12
|
+
class MethodValidation
|
13
|
+
|
14
|
+
# fully qualified method name
|
15
|
+
attr_accessor :method_name
|
16
|
+
|
17
|
+
# parameters expected by the method
|
18
|
+
attr_accessor :parameters
|
19
|
+
|
20
|
+
#
|
21
|
+
# MethodValidation constructor
|
22
|
+
# @param method_name fully qualified method name (Module::Class::method)
|
23
|
+
# @param block the block to be executed
|
24
|
+
#
|
25
|
+
def initialize(method_name, &block)
|
26
|
+
@method_name = method_name
|
27
|
+
@parameters = []
|
28
|
+
block_given? and self.instance_eval &block
|
29
|
+
end
|
30
|
+
|
31
|
+
# get mandatory parameters
|
32
|
+
def mandatories
|
33
|
+
values = []
|
34
|
+
@parameters.each{|param|
|
35
|
+
param.mandatory? and values << param
|
36
|
+
}
|
37
|
+
values
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Execute validation block in this object scope
|
42
|
+
#
|
43
|
+
def block(&block)
|
44
|
+
block_given? and self.instance_eval &block
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# DSL that defines the validation rules.
|
49
|
+
# parameter (Object, :optional = false) { block }
|
50
|
+
#
|
51
|
+
def method_missing(meth, *args, &block)
|
52
|
+
|
53
|
+
if args.length < 2
|
54
|
+
optional = false
|
55
|
+
else
|
56
|
+
if args[1].eql?(:optional)
|
57
|
+
optional = true
|
58
|
+
else
|
59
|
+
optional = false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
parameter = Parameter.new(meth, args.length < 1 ? Object : args[0], optional, block)
|
64
|
+
@parameters.push parameter
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# Juan de Bravo <juandebravo@gmail.com>
|
3
|
+
#
|
4
|
+
|
5
|
+
module ParamsValidator
|
6
|
+
|
7
|
+
#
|
8
|
+
# Parameter definition
|
9
|
+
#
|
10
|
+
class Parameter
|
11
|
+
|
12
|
+
# parameter name
|
13
|
+
attr_accessor :name
|
14
|
+
|
15
|
+
# set if parameter is mandatory or optional
|
16
|
+
attr_accessor :optional
|
17
|
+
|
18
|
+
# parameter type (Object by default)
|
19
|
+
attr_accessor :klass
|
20
|
+
|
21
|
+
# specific ruleset (i.e. max or min length)
|
22
|
+
attr_accessor :rule
|
23
|
+
|
24
|
+
def initialize(name, klass = Object, optional = false, rule = nil)
|
25
|
+
@name = name.to_sym
|
26
|
+
@optional = optional
|
27
|
+
@klass = klass
|
28
|
+
@rule = rule
|
29
|
+
end
|
30
|
+
|
31
|
+
def optional?
|
32
|
+
@optional
|
33
|
+
end
|
34
|
+
|
35
|
+
def mandatory?
|
36
|
+
!@optional
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'params_validator/validator'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Juan de Bravo <juandebravo@gmail.com>
|
5
|
+
#
|
6
|
+
|
7
|
+
module ParamsValidator
|
8
|
+
#
|
9
|
+
# Class used to enhance the way to pass parameters to a method
|
10
|
+
#
|
11
|
+
class Request < Hash
|
12
|
+
|
13
|
+
def initialize(params = nil)
|
14
|
+
super(params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(key, value)
|
18
|
+
self[key.to_sym] = value
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
alias :delete_old :delete
|
23
|
+
|
24
|
+
def delete(key)
|
25
|
+
delete_old(key)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def params
|
30
|
+
keys
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :size :length
|
34
|
+
|
35
|
+
def validate(ruleset)
|
36
|
+
ParamsValidator::Validator.validate_ruleset(ruleset, self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid?(ruleset)
|
40
|
+
begin
|
41
|
+
validate(ruleset)
|
42
|
+
true
|
43
|
+
rescue
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#
|
2
|
+
# Juan de Bravo <juandebravo@gmail.com>
|
3
|
+
#
|
4
|
+
|
5
|
+
module ParamsValidator
|
6
|
+
|
7
|
+
#
|
8
|
+
# Module to be included in a class which methods should be validated
|
9
|
+
#
|
10
|
+
module ValidParams
|
11
|
+
|
12
|
+
def self.included(base)
|
13
|
+
base.extend(ClassMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# This method is called to validate the request parameters to a specific method before calling the method itself
|
18
|
+
# @param params Hash of parameters to validate
|
19
|
+
# @param interface_method String containing the fully qualified method name (Module1::Module2::Class::method)
|
20
|
+
#
|
21
|
+
def previous_validation(params = nil, interface_method = nil)
|
22
|
+
unless validator.nil?
|
23
|
+
if interface_method.nil?
|
24
|
+
interface = caller[0][/^(.*)(\.rb).*$/, 1].split('/').last
|
25
|
+
interface = caller[0][/^(.*)(\.rb).*$/, 1].split('/')
|
26
|
+
interface.shift
|
27
|
+
interface = interface.map!{|x| x.capitalize}.join("::")
|
28
|
+
method = caller[0][/`([^']*)'/, 1]
|
29
|
+
interface_method = [interface, method].join("::")
|
30
|
+
else
|
31
|
+
# Got directly the method name in interface_method
|
32
|
+
end
|
33
|
+
params.instance_of?(Array) and params = params[0]
|
34
|
+
validator.validate_params(interface_method, params)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def validator
|
39
|
+
self.class.validator
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_rules(rules)
|
43
|
+
self.class.load_rules(rules)
|
44
|
+
end
|
45
|
+
|
46
|
+
# inner module to define class methods
|
47
|
+
module ClassMethods
|
48
|
+
|
49
|
+
# This method is used in classes to define which methods
|
50
|
+
# should be validated when called.
|
51
|
+
# i.e. validate_method :method1
|
52
|
+
# validate_method [:method1, :method2]
|
53
|
+
def validate_method(method, &block)
|
54
|
+
# get the fully qualified method name
|
55
|
+
interface = self.name
|
56
|
+
|
57
|
+
# cast to array if method is one symbol
|
58
|
+
method.instance_of?(Symbol) and method = [method]
|
59
|
+
|
60
|
+
# wrap each method
|
61
|
+
method.each{|m|
|
62
|
+
interface_method = [interface, m].join("::")
|
63
|
+
|
64
|
+
# add validation rule to the specific method if a block is defined
|
65
|
+
if block_given?
|
66
|
+
validator.validation_rule(interface_method, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
# wrap old method with the previous validation
|
70
|
+
old_method = "#{m}_old"
|
71
|
+
self.send :alias_method, *[old_method, m]
|
72
|
+
|
73
|
+
define_method(m) do |*args, &block|
|
74
|
+
# validate parameters
|
75
|
+
previous_validation(args, interface_method)
|
76
|
+
# call method
|
77
|
+
send(old_method, *args, &block)
|
78
|
+
end
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
# get the specified rule for a method
|
83
|
+
def get_rule(method)
|
84
|
+
object_name = self.name
|
85
|
+
key = "#{object_name}::#{method}"
|
86
|
+
method_validation = validator.methods_loaded[key.to_sym]
|
87
|
+
unless method_validation.nil?
|
88
|
+
return method_validation.parameters
|
89
|
+
end
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# validator object
|
94
|
+
def validator
|
95
|
+
@@validator ||= Validator.new
|
96
|
+
end
|
97
|
+
|
98
|
+
# shortcut to validator.load_rules
|
99
|
+
def load_rules(rules)
|
100
|
+
validator.load_rules(rules)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'params_validator/method_validation'
|
2
|
+
require 'params_validator/valid_params'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Juan de Bravo <juandebravo@gmail.com>
|
6
|
+
#
|
7
|
+
|
8
|
+
module ParamsValidator
|
9
|
+
|
10
|
+
#
|
11
|
+
# This class
|
12
|
+
#
|
13
|
+
class Validator
|
14
|
+
|
15
|
+
ERROR_MESSAGE_NULL = "Parameter %s cannot be null"
|
16
|
+
ERROR_MESSAGE_TYPE = "Parameter %s present but invalid type %s"
|
17
|
+
ERROR_MESSAGE_BLOCK = "Parameter %s present but does not match the ruleset"
|
18
|
+
|
19
|
+
attr_reader :methods_loaded
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@methods_loaded = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# This method loads new rules in memory
|
27
|
+
# validatation_rule method do
|
28
|
+
# param1 (type) &block
|
29
|
+
# param2 (type) &block
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
def load_rules(rules)
|
33
|
+
self.instance_eval(rules)
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# This method is part of the DSL and defines a new validator rule
|
38
|
+
# @param method_name fully qualified method name (Module::Class::method)
|
39
|
+
# @param block the block to be executed
|
40
|
+
#
|
41
|
+
def validation_rule(method_name, &block)
|
42
|
+
method = MethodValidation.new(method_name)
|
43
|
+
block_given? and method.block &block
|
44
|
+
@methods_loaded[:"#{method_name}"] = method
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# This method validates if the specific call to method_name is valid
|
49
|
+
# @param method_name fully qualified method name (Module::Class::method)
|
50
|
+
# @param params
|
51
|
+
#
|
52
|
+
def validate_params(method_name, params)
|
53
|
+
errors = []
|
54
|
+
|
55
|
+
# fetch method rulesets
|
56
|
+
method = @methods_loaded[method_name.to_sym]
|
57
|
+
|
58
|
+
if method.nil?
|
59
|
+
# TODO enable devel or prod mode to raise or not an exception
|
60
|
+
errors.push "Unable to validate method #{method_name} with (#{@methods_loaded.keys.length}) keys #{@methods_loaded.keys}"
|
61
|
+
raise ArgumentError, errors
|
62
|
+
end
|
63
|
+
|
64
|
+
# fetch all params (optional and mandatory)
|
65
|
+
check_params = method.parameters
|
66
|
+
|
67
|
+
self.class.validate_ruleset(check_params, params)
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# This method validates a params hash against a specific rulset
|
73
|
+
# @param valid_params ruleset
|
74
|
+
# @param params
|
75
|
+
#
|
76
|
+
def Validator.validate_ruleset(valid_params, params)
|
77
|
+
errors = []
|
78
|
+
if !valid_params.nil? and params.nil?
|
79
|
+
errors.push "Nil parameters when #{valid_params.length} expected"
|
80
|
+
raise ArgumentError, errors
|
81
|
+
end
|
82
|
+
|
83
|
+
# if just one param -> include as array with length 1
|
84
|
+
if valid_params.instance_of?(Array) && valid_params.length == 1 && params.instance_of?(String)
|
85
|
+
params = {valid_params[0].name.to_sym => params}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Validate the params
|
89
|
+
valid_params.each{|key|
|
90
|
+
# get param
|
91
|
+
param = params[key.name.to_sym]
|
92
|
+
check_result = Validator.check_param(key, param)
|
93
|
+
unless check_result.nil?
|
94
|
+
errors.push check_result
|
95
|
+
end
|
96
|
+
}
|
97
|
+
unless errors.empty?
|
98
|
+
raise ArgumentError, errors
|
99
|
+
end
|
100
|
+
# no exception -> successfully validated
|
101
|
+
true
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# This method validates if the specific method is valid
|
107
|
+
# @param valid_param object containing the param ruleset
|
108
|
+
# @param param param specified by the user in the method call
|
109
|
+
#
|
110
|
+
def Validator.check_param(valid_param, param)
|
111
|
+
if valid_param.optional? and param.nil? # argument optional and not present -> continue
|
112
|
+
return nil
|
113
|
+
end
|
114
|
+
|
115
|
+
if param.nil? # argument mandatory and not present
|
116
|
+
return ERROR_MESSAGE_NULL % valid_param.name
|
117
|
+
else
|
118
|
+
# check argument type is valid
|
119
|
+
unless param.is_a?(valid_param.klass)
|
120
|
+
return ERROR_MESSAGE_TYPE % [valid_param.name, param.class]
|
121
|
+
end
|
122
|
+
|
123
|
+
# check argument satisfies ruleset (if present)
|
124
|
+
unless valid_param.rule.nil?
|
125
|
+
!valid_param.rule.call(param) and return ERROR_MESSAGE_BLOCK % valid_param.name
|
126
|
+
end
|
127
|
+
end
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("lib", ".")
|
3
|
+
|
4
|
+
require "params_validator/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "params-validator"
|
8
|
+
s.version = ParamsValidator::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Juan de Bravo"]
|
11
|
+
s.email = ["juandebravo@gmail.com"]
|
12
|
+
s.homepage = ""
|
13
|
+
s.summary = "params-validators allows to validate the required/optional parameters in a method"
|
14
|
+
s.description = "params-validators allows to validate the required/optional parameters in a method"
|
15
|
+
|
16
|
+
s.rubyforge_project = "params-validator"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
|
23
|
+
end
|
data/test/main.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
|
2
|
+
|
3
|
+
require 'params-validator'
|
4
|
+
require 'project/provisioning/user_object'
|
5
|
+
require 'project/provisioning/application'
|
6
|
+
|
7
|
+
if __FILE__ == $0
|
8
|
+
rules = <<EOF
|
9
|
+
validation_rule "Project::Provisioning::UserObject::create" do
|
10
|
+
name (String) {|value| value.length > 5 && value.length < 10}
|
11
|
+
password String
|
12
|
+
birthday (Fixnum) {|value| Time.now.year > value}
|
13
|
+
description(String, :optional) {|value| value.length > 50 && value.length < 100}
|
14
|
+
end
|
15
|
+
|
16
|
+
validation_rule "Project::Provisioning::UserObject::delete" do
|
17
|
+
user_id (String)
|
18
|
+
end
|
19
|
+
EOF
|
20
|
+
|
21
|
+
include ParamsValidator::ValidParams
|
22
|
+
|
23
|
+
load_rules(rules)
|
24
|
+
|
25
|
+
|
26
|
+
user = Project::Provisioning::UserObject.new
|
27
|
+
begin
|
28
|
+
user.create({:name => "juan", :password1 => "project", :birthday => 1978})
|
29
|
+
rescue ArgumentError => ex
|
30
|
+
p ex.message
|
31
|
+
end
|
32
|
+
user.delete({:user_id => "juan"})
|
33
|
+
|
34
|
+
application = Project::Provisioning::Application.new
|
35
|
+
application.create({:user_id => "juan"})
|
36
|
+
|
37
|
+
application.delete({:app_id => "app1"})
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'params-validator'
|
2
|
+
|
3
|
+
describe ParamsValidator::MethodValidation do
|
4
|
+
describe "method_name" do
|
5
|
+
it "method_name returns the valid method name" do
|
6
|
+
method = ParamsValidator::MethodValidation.new("method_name")
|
7
|
+
method.method_name.should == "method_name"
|
8
|
+
end
|
9
|
+
it "method_name with module/class returns the valid method name" do
|
10
|
+
method = ParamsValidator::MethodValidation.new("Module1::Module2::Class::method")
|
11
|
+
method.method_name.should eq("Module1::Module2::Class::method")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "parameters" do
|
16
|
+
proc = lambda{
|
17
|
+
name(String) {|value| value.length > 5 && value.length < 10}
|
18
|
+
password
|
19
|
+
birthday(Fixnum) {|value| Time.now.year > value}
|
20
|
+
description(String, :optional) {|value| value.length > 50 && value.length < 100}
|
21
|
+
}
|
22
|
+
|
23
|
+
it "params length should be 4" do
|
24
|
+
method = ParamsValidator::MethodValidation.new("Module::Class:method", &proc)
|
25
|
+
method.parameters.length.should == 4
|
26
|
+
end
|
27
|
+
|
28
|
+
it "mandatory params length should be 3" do
|
29
|
+
method = ParamsValidator::MethodValidation.new("Module::Class:method", &proc)
|
30
|
+
method.parameters.length.should == 4
|
31
|
+
end
|
32
|
+
|
33
|
+
it "default object should be Object" do
|
34
|
+
method = ParamsValidator::MethodValidation.new("Module::Class:method", &proc)
|
35
|
+
method.parameters[1].klass.should == Object
|
36
|
+
end
|
37
|
+
|
38
|
+
it "parameter with ruleset should have rule attribute" do
|
39
|
+
method = ParamsValidator::MethodValidation.new("Module::Class:method", &proc)
|
40
|
+
method.parameters[0].rule.should_not == nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "parameter without ruleset should have nil rule attribute" do
|
44
|
+
method = ParamsValidator::MethodValidation.new("Module::Class:method", &proc)
|
45
|
+
method.parameters[1].rule.should == nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'params-validator'
|
2
|
+
|
3
|
+
module Mock
|
4
|
+
class MockObject
|
5
|
+
include ParamsValidator::ValidParams
|
6
|
+
|
7
|
+
[:log, :log_level, :log_level_type, :log_level_type_optional, :log_data, :log_data_block].each{|m|
|
8
|
+
define_method(m) do |*args, &block|
|
9
|
+
#puts "call to method #{m.to_s}"
|
10
|
+
true
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
validate_method(:log) do
|
15
|
+
end
|
16
|
+
validate_method(:log_level) do
|
17
|
+
level
|
18
|
+
end
|
19
|
+
validate_method(:log_level_type) do
|
20
|
+
level Fixnum
|
21
|
+
end
|
22
|
+
validate_method(:log_level_type_optional) do
|
23
|
+
level(Fixnum, :optional)
|
24
|
+
end
|
25
|
+
validate_method(:log_data) do
|
26
|
+
data(String)
|
27
|
+
level(Fixnum, :optional)
|
28
|
+
end
|
29
|
+
validate_method(:log_data_block) do
|
30
|
+
data(String) { |data| !data.nil? and data.length > 0}
|
31
|
+
level(Fixnum, :optional) {|level| level <= 3}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
|
2
|
+
|
3
|
+
require 'params-validator'
|
4
|
+
|
5
|
+
describe ParamsValidator::Parameter do
|
6
|
+
describe "optional" do
|
7
|
+
#optional
|
8
|
+
it "optional? returns true if parameter is optional" do
|
9
|
+
param = ParamsValidator::Parameter.new("parameter", Object, true, nil)
|
10
|
+
param.optional?.should == true
|
11
|
+
end
|
12
|
+
it "optional? returns false if parameter is mandatory" do
|
13
|
+
param = ParamsValidator::Parameter.new("parameter", Object, false, nil)
|
14
|
+
param.optional?.should == false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "ruleset" do
|
19
|
+
# ruleset
|
20
|
+
it "rule returns nil if parameter has no ruleset defined" do
|
21
|
+
param = ParamsValidator::Parameter.new("parameter", Object, false, nil)
|
22
|
+
param.rule.should == nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "klass" do
|
27
|
+
# klass
|
28
|
+
it "klass returns parameter class if defined" do
|
29
|
+
param = ParamsValidator::Parameter.new("parameter", String)
|
30
|
+
param.klass.should == String
|
31
|
+
end
|
32
|
+
it "klass returns Object class if undefined" do
|
33
|
+
param = ParamsValidator::Parameter.new("parameter")
|
34
|
+
param.klass.should == Object
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'params-validator'
|
2
|
+
|
3
|
+
module Project::Provisioning
|
4
|
+
class Application
|
5
|
+
include ParamsValidator::ValidParams
|
6
|
+
|
7
|
+
def create(params)
|
8
|
+
puts "create a specific #{self.class.name}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def delete(params)
|
12
|
+
puts "delete a specific #{self.class.name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
rules = <<EOF
|
16
|
+
validation_rule "Project::Provisioning::Application::create" do
|
17
|
+
user_id (String)
|
18
|
+
end
|
19
|
+
EOF
|
20
|
+
|
21
|
+
load_rules(rules)
|
22
|
+
|
23
|
+
|
24
|
+
validate_method :create
|
25
|
+
|
26
|
+
validate_method(:delete) {
|
27
|
+
app_id (String)
|
28
|
+
}
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'params-validator'
|
2
|
+
|
3
|
+
module Project
|
4
|
+
module Provisioning
|
5
|
+
class UserObject
|
6
|
+
include ParamsValidator::ValidParams
|
7
|
+
|
8
|
+
def create(params)
|
9
|
+
puts "create a specific user"
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete(params)
|
13
|
+
puts "delete a specific user"
|
14
|
+
end
|
15
|
+
|
16
|
+
validate_method [:delete, :create]
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),'.')
|
2
|
+
|
3
|
+
require 'params-validator'
|
4
|
+
require 'mock/mock_object'
|
5
|
+
require 'yamock_object'
|
6
|
+
|
7
|
+
|
8
|
+
describe ParamsValidator::Request do
|
9
|
+
describe "handle parameters" do
|
10
|
+
|
11
|
+
it "add any parameter" do
|
12
|
+
obj = ParamsValidator::Request.new
|
13
|
+
obj.add(:foo, "bar")
|
14
|
+
obj.add(:length, 3)
|
15
|
+
obj.size.should eq(2)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "delete any parameter" do
|
19
|
+
obj = ParamsValidator::Request.new
|
20
|
+
obj.add(:foo, "bar")
|
21
|
+
obj.add(:length, 3)
|
22
|
+
obj.delete(:length)
|
23
|
+
obj.size.should eq(1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "validate parameters" do
|
28
|
+
|
29
|
+
it "validation return true with valid parameters" do
|
30
|
+
obj = ParamsValidator::Request.new
|
31
|
+
obj[:data] = "this is a log"
|
32
|
+
obj[:level] = 1
|
33
|
+
ruleset = Mock::MockObject.get_rule(:log_data_block)
|
34
|
+
obj.validate(ruleset).should eq(true)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "validation throw exception with invalid parameters" do
|
38
|
+
obj = ParamsValidator::Request.new
|
39
|
+
obj[:data] = "this is a log"
|
40
|
+
obj[:level] = "1"
|
41
|
+
ruleset = Mock::MockObject.get_rule(:log_data_block)
|
42
|
+
lambda{obj.validate(ruleset)}.should raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "validation throw exception with the correct number of errors" do
|
46
|
+
obj = ParamsValidator::Request.new
|
47
|
+
obj[:data] = ""
|
48
|
+
obj[:level] = "1"
|
49
|
+
ruleset = Mock::MockObject.get_rule(:log_data_block)
|
50
|
+
begin
|
51
|
+
obj.validate(ruleset)
|
52
|
+
rescue ArgumentError => ae
|
53
|
+
ae.message.length.should eq(2)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "valid? method" do
|
60
|
+
|
61
|
+
it "returns true if valid" do
|
62
|
+
obj = ParamsValidator::Request.new
|
63
|
+
obj[:data] = "this is a log"
|
64
|
+
obj[:level] = 1
|
65
|
+
ruleset = Mock::MockObject.get_rule(:log_data_block)
|
66
|
+
obj.valid?(ruleset).should eq(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns false if invalid" do
|
70
|
+
obj = ParamsValidator::Request.new
|
71
|
+
obj[:data] = "this is a log"
|
72
|
+
obj[:level] = "1"
|
73
|
+
ruleset = Mock::MockObject.get_rule(:log_data_block)
|
74
|
+
obj.valid?(ruleset).should eq(false)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),'.')
|
2
|
+
|
3
|
+
require 'params-validator'
|
4
|
+
require 'mock/mock_object'
|
5
|
+
require 'yamock_object'
|
6
|
+
|
7
|
+
include Mock
|
8
|
+
|
9
|
+
describe ParamsValidator::ValidParams do
|
10
|
+
describe "validate_method inside class" do
|
11
|
+
it "executes an empty block and validates true always" do
|
12
|
+
obj = MockObject.new
|
13
|
+
obj.log({}).should eq(true)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises an exception if mandatory parameter missing" do
|
17
|
+
obj = MockObject.new
|
18
|
+
lambda{obj.log_level({})}.should raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "raises an exception if mandatory parameter included but invalid type" do
|
22
|
+
obj = MockObject.new
|
23
|
+
lambda{obj.log_level_type({:level => "INFO"})}.should raise_error(ArgumentError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises an exception if optional parameter included but invalid type" do
|
27
|
+
obj = MockObject.new
|
28
|
+
lambda{obj.log_level_type_optional({:level => "INFO"})}.should raise_error(ArgumentError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "executes a valid ruleset with mandatory parameters" do
|
32
|
+
obj = MockObject.new
|
33
|
+
obj.log_level_type({:level => 3}).should eq(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "executes a valid ruleset with mandatory and optional parameters included" do
|
37
|
+
obj = MockObject.new
|
38
|
+
obj.log_data({:level => 3, :data => "This is a test"}).should eq(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "executes a valid ruleset with mandatory parameters included and optional parameters missing" do
|
42
|
+
obj = MockObject.new
|
43
|
+
obj.log_data({:data => "This is a test"}).should eq(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "executes a valid ruleset with validation block for parameters" do
|
47
|
+
obj = MockObject.new
|
48
|
+
obj.log_data_block({:data => "This is a test", :level => 1}).should eq(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "executes a valid ruleset with invalid validation block for mandatory parameter" do
|
52
|
+
obj = MockObject.new
|
53
|
+
lambda{obj.log_data_block({:data => ""})}.should raise_error(ArgumentError)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "executes a valid ruleset with invalid validation block for optional parameter" do
|
57
|
+
obj = MockObject.new
|
58
|
+
lambda{obj.log_data_block({:data => "", :level => 5})}.should raise_error(ArgumentError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "validate_method inline" do
|
63
|
+
rules = <<EOF
|
64
|
+
validation_rule("YamockObject::log") do
|
65
|
+
end
|
66
|
+
validation_rule("YamockObject::log_level") do
|
67
|
+
level
|
68
|
+
end
|
69
|
+
validation_rule("YamockObject::log_level_type") do
|
70
|
+
level Fixnum
|
71
|
+
end
|
72
|
+
validation_rule("YamockObject::log_level_type_optional") do
|
73
|
+
level(Fixnum, :optional)
|
74
|
+
end
|
75
|
+
validation_rule("YamockObject::log_data") do
|
76
|
+
data(String)
|
77
|
+
level(Fixnum, :optional)
|
78
|
+
end
|
79
|
+
validation_rule("YamockObject::log_data_block") do
|
80
|
+
data(String) { |data| !data.nil? and data.length > 0}
|
81
|
+
level(Fixnum, :optional) {|level| level <= 3}
|
82
|
+
end
|
83
|
+
|
84
|
+
EOF
|
85
|
+
|
86
|
+
include ParamsValidator::ValidParams
|
87
|
+
load_rules(rules)
|
88
|
+
|
89
|
+
it "executes a valid ruleset with invalid validation block for optional parameter" do
|
90
|
+
obj = YamockObject.new
|
91
|
+
lambda{obj.log_data_block({:data => "", :level => 5})}.should raise_error(ArgumentError)
|
92
|
+
end
|
93
|
+
it "executes a valid ruleset with valid validation blocks" do
|
94
|
+
obj = YamockObject.new
|
95
|
+
obj.log_data_block({:data => "info", :level => 2}).should eq(true)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'params-validator'
|
2
|
+
|
3
|
+
class YamockObject
|
4
|
+
include ParamsValidator::ValidParams
|
5
|
+
|
6
|
+
METHODS = [:log, :log_level, :log_level_type, :log_level_type_optional, :log_data, :log_data_block]
|
7
|
+
|
8
|
+
METHODS.each{|m|
|
9
|
+
define_method(m) do |*args, &block|
|
10
|
+
true
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
validate_method METHODS
|
15
|
+
end
|
16
|
+
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: params-validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Juan de Bravo
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-24 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: params-validators allows to validate the required/optional parameters in a method
|
23
|
+
email:
|
24
|
+
- juandebravo@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- .rvmrc
|
34
|
+
- Gemfile
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- lib/params-validator.rb
|
38
|
+
- lib/params_validator/method_validation.rb
|
39
|
+
- lib/params_validator/parameter.rb
|
40
|
+
- lib/params_validator/request.rb
|
41
|
+
- lib/params_validator/valid_params.rb
|
42
|
+
- lib/params_validator/validator.rb
|
43
|
+
- lib/params_validator/version.rb
|
44
|
+
- params-validator.gemspec
|
45
|
+
- test/main.rb
|
46
|
+
- test/method_validation_spec.rb
|
47
|
+
- test/mock/mock_object.rb
|
48
|
+
- test/parameter_spec.rb
|
49
|
+
- test/project/provisioning/application.rb
|
50
|
+
- test/project/provisioning/user_object.rb
|
51
|
+
- test/request_spec.rb
|
52
|
+
- test/valid_params_spec.rb
|
53
|
+
- test/yamock_object.rb
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: ""
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project: params-validator
|
84
|
+
rubygems_version: 1.4.2
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: params-validators allows to validate the required/optional parameters in a method
|
88
|
+
test_files:
|
89
|
+
- test/main.rb
|
90
|
+
- test/method_validation_spec.rb
|
91
|
+
- test/mock/mock_object.rb
|
92
|
+
- test/parameter_spec.rb
|
93
|
+
- test/project/provisioning/application.rb
|
94
|
+
- test/project/provisioning/user_object.rb
|
95
|
+
- test/request_spec.rb
|
96
|
+
- test/valid_params_spec.rb
|
97
|
+
- test/yamock_object.rb
|