validate_my_routes 1.0.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.
- checksums.yaml +7 -0
- data/lib/validate_my_routes.rb +9 -0
- data/lib/validate_my_routes/errors.rb +42 -0
- data/lib/validate_my_routes/validatable.rb +102 -0
- data/lib/validate_my_routes/validate.rb +27 -0
- data/lib/validate_my_routes/validate/convert_to_type.rb +80 -0
- data/lib/validate_my_routes/validate/mixins/macros.rb +51 -0
- data/lib/validate_my_routes/validate/mixins/rules_combinators.rb +30 -0
- data/lib/validate_my_routes/validate/rules.rb +61 -0
- data/lib/validate_my_routes/validate/rules/all_parameters.rb +75 -0
- data/lib/validate_my_routes/validate/rules/anything.rb +13 -0
- data/lib/validate_my_routes/validate/rules/comparable.rb +82 -0
- data/lib/validate_my_routes/validate/rules/compound.rb +41 -0
- data/lib/validate_my_routes/validate/rules/conditional.rb +21 -0
- data/lib/validate_my_routes/validate/rules/enum.rb +21 -0
- data/lib/validate_my_routes/validate/rules/of_type.rb +31 -0
- data/lib/validate_my_routes/validate/rules/required.rb +17 -0
- data/lib/validate_my_routes/validate/rules/transforms.rb +50 -0
- data/lib/validate_my_routes/validate/validation_rule.rb +123 -0
- data/lib/validate_my_routes/validation_rules.rb +29 -0
- data/lib/validate_my_routes/version.rb +4 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7bbe49d25595b0b18e832e1296bef3e8ba29cc6d
|
4
|
+
data.tar.gz: de5cbfe90139663a05c9055b6696e7a846fa6f30
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fdb2afba0936e7f025cc4f375a01dcc1312e7bfa466c001e1ea4c7031f6474af968919d6d5151fbed68df6fc374e5cbd3a77582e606f00fa035d577627c72976
|
7
|
+
data.tar.gz: fb517bac0d2b6c368e00b024ad5f35ef3f2aa9a8d575cbf5712b3274764938050a385a96d9174b8afe911c61513a195871513dfed0cd6f47410dc0f3be8b3be3
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative 'validate_my_routes/version'
|
2
|
+
require_relative 'validate_my_routes/errors'
|
3
|
+
require_relative 'validate_my_routes/validation_rules'
|
4
|
+
require_relative 'validate_my_routes/validate'
|
5
|
+
require_relative 'validate_my_routes/validatable'
|
6
|
+
|
7
|
+
# General module that defines the base access to ValidateMyRoutes
|
8
|
+
module ValidateMyRoutes
|
9
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
# Defining errors
|
3
|
+
module Errors
|
4
|
+
# Base error for validate_my_routes
|
5
|
+
class Error < ::RuntimeError; end
|
6
|
+
|
7
|
+
# Raised when type conversion fails
|
8
|
+
class InvalidTypeError < Error; end
|
9
|
+
|
10
|
+
# Raised when rule is not following required protocol
|
11
|
+
class UnsupportedRuleError < Error; end
|
12
|
+
|
13
|
+
# Raised when using validation DSL and missing validation block
|
14
|
+
class MissingValidationDeclarationBlock < Error; end
|
15
|
+
|
16
|
+
# Raised when using validation DSL when validation rule is already defined
|
17
|
+
class ValidationRuleNamingConflict < Error; end
|
18
|
+
|
19
|
+
# Raised when rule is missused
|
20
|
+
class MissusedRuleError < Error; end
|
21
|
+
|
22
|
+
# Basic error raised for validation failures
|
23
|
+
class ValidationError < Error
|
24
|
+
attr_reader :status_code, :message
|
25
|
+
def initialize(message, status_code)
|
26
|
+
super(message)
|
27
|
+
@status_code = status_code
|
28
|
+
@message = message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Raised when soft failure occurs
|
33
|
+
class ConditionalValidationError < ValidationError; end
|
34
|
+
|
35
|
+
# Raised when exceptions occurs in validation block
|
36
|
+
class ValidationRaisedAnExceptionError < ValidationError
|
37
|
+
def initialize(custom_exception, status_code)
|
38
|
+
super(custom_exception.to_s, status_code)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
# Route parameters validation extension
|
3
|
+
# To start using it, the extension needs to be registered
|
4
|
+
#
|
5
|
+
# register ValidateMyRoutes::Validatable
|
6
|
+
#
|
7
|
+
# Registering Validatable extension adds two conditions:
|
8
|
+
# - validate_all_params - a list of rules that need to be applied to all parameters together
|
9
|
+
# - validate_params - a hash with parameter names as keys and rules with extra information
|
10
|
+
# in values
|
11
|
+
module Validatable
|
12
|
+
class << self
|
13
|
+
def registered(app)
|
14
|
+
add_validate_params_condition_to app
|
15
|
+
add_validate_all_params_condition_to app
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def add_validate_all_params_condition_to(app)
|
21
|
+
app.set(:validate_all_params) do |*rules|
|
22
|
+
condition do
|
23
|
+
rules.all? { |rule| Validate.validate!(self, rule, params, false) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# rubocop:disable AbcSize
|
29
|
+
def add_validate_params_condition_to(app)
|
30
|
+
app.set(:validate_params) do |*validations|
|
31
|
+
condition do
|
32
|
+
path_validations = validations.select { |_, rule| rule[:path_param] }
|
33
|
+
query_validations = validations.reject { |_, rule| rule[:path_param] }
|
34
|
+
|
35
|
+
[path_validations, query_validations].all? do |param_validations|
|
36
|
+
param_validations.select { |_, rule| rule[:path_param] }.all? do |param_name, rule|
|
37
|
+
value = params[param_name]
|
38
|
+
Validate.validate!(self, rule[:rule], value, rule[:path_param], param_name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# rubocop:enable AbcSize
|
46
|
+
|
47
|
+
# Define path parameter with validation for all routes (including nested routes)
|
48
|
+
#
|
49
|
+
# param_validation :service_id, from_enum(%w[a b c])
|
50
|
+
def param_validation(name, rule)
|
51
|
+
Validate::Rules.validate_single_param_rule! rule
|
52
|
+
(@param_validations ||= {})[name.to_sym] = rule
|
53
|
+
end
|
54
|
+
|
55
|
+
# Define all parameters validation for a single route
|
56
|
+
#
|
57
|
+
# all_params_validation at_least_one_of(%i[version class status owner])
|
58
|
+
# get '/' do
|
59
|
+
# # params contain at least one of :version, :class, :status or :owner parameter
|
60
|
+
# end
|
61
|
+
def all_params_validation(rule)
|
62
|
+
Validate::Rules.validate_all_params_rule! rule
|
63
|
+
(@all_params_validation ||= []) << rule
|
64
|
+
end
|
65
|
+
|
66
|
+
# Hook into .route Sinatra method to add validation for parameters
|
67
|
+
def route(verb, route_pattern, conditions = {}, &block)
|
68
|
+
route_path_parameters(route_pattern).each do |name|
|
69
|
+
next unless param_validations.key? name
|
70
|
+
|
71
|
+
rule = param_validations[name]
|
72
|
+
# Add path parameter validation if it was specified
|
73
|
+
(conditions[:validate_params] ||= {})[name] ||= { path_param: true, rule: rule }
|
74
|
+
end
|
75
|
+
|
76
|
+
# Add all params validation if it was specified
|
77
|
+
conditions[:validate_all_params] = @all_params_validation if @all_params_validation
|
78
|
+
@all_params_validation = nil # remove params validation as it is defined on per-route bases
|
79
|
+
|
80
|
+
super(verb, route_pattern, conditions, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def route_path_parameters(route_pattern)
|
84
|
+
path_parameters = route_pattern.split('/').map do |part|
|
85
|
+
part.start_with?(':') ? part[1..-1].to_sym : nil
|
86
|
+
end
|
87
|
+
|
88
|
+
path_parameters.flatten.compact.uniq.map(&:to_sym)
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def param_validations
|
94
|
+
parameters_defined_in_superclass = {}
|
95
|
+
# For nested routes we need to look for defined parameters with validation in
|
96
|
+
# superclass also.
|
97
|
+
parameters_defined_in_superclass = superclass.param_validations \
|
98
|
+
if superclass.respond_to?(:param_validations, true)
|
99
|
+
parameters_defined_in_superclass.merge(@param_validations || {})
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'validate/convert_to_type'
|
2
|
+
require_relative 'validate/rules'
|
3
|
+
|
4
|
+
module ValidateMyRoutes
|
5
|
+
# Module for validation. Provides method to validate value by specified rule.
|
6
|
+
module Validate
|
7
|
+
class << self
|
8
|
+
# Perform validation of a single rule in-place
|
9
|
+
# Note: this method is not validating that rule is for all parameters or just a single
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# get 'some/:id' do |id|
|
13
|
+
# ValidateMyRoutes::Validate.validate!(self, greater_than(5), id.to_i, 'id') do |msg|
|
14
|
+
# halt 400, "Id <#{id}> failed validation: #{msg}"
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
def validate!(app, rule, *args)
|
18
|
+
rule.validate!(app, *args)
|
19
|
+
rescue Errors::ConditionalValidationError
|
20
|
+
false
|
21
|
+
rescue Errors::ValidationError => failure
|
22
|
+
app.halt failure.status_code, failure.message unless block_given?
|
23
|
+
yield failure.message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module ValidateMyRoutes
|
4
|
+
module Validate
|
5
|
+
# ConvertToType module provides single method convert_to_type to convert value into type
|
6
|
+
# to_type. Conversion can fail with InvalidTypeError.
|
7
|
+
module ConvertToType
|
8
|
+
class << self
|
9
|
+
Boolean = :Boolean # rubocop:disable Naming/ConstantName
|
10
|
+
SIMPLE_TYPES = [Float, String, Date, Time, DateTime, Integer].freeze
|
11
|
+
COMPOSITE_TYPES = [Array, Hash].freeze
|
12
|
+
BOOLEAN_TYPES = [Boolean, TrueClass, FalseClass].freeze
|
13
|
+
|
14
|
+
def convert_to_type(value, to_type)
|
15
|
+
return value if already_of_type?(value, to_type)
|
16
|
+
|
17
|
+
if SIMPLE_TYPES.include?(to_type)
|
18
|
+
parse_simple_type(value, to_type)
|
19
|
+
elsif COMPOSITE_TYPES.include?(to_type)
|
20
|
+
parse_composite_type(value, to_type)
|
21
|
+
elsif BOOLEAN_TYPES.include?(to_type)
|
22
|
+
parse_boolean(value)
|
23
|
+
else
|
24
|
+
raise_unknown_type(to_type)
|
25
|
+
end
|
26
|
+
rescue ArgumentError
|
27
|
+
raise_with_invalid_type(value, to_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def already_of_type?(value, typ)
|
33
|
+
(typ.is_a?(Class) || typ.is_a?(Module)) && value.is_a?(typ)
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_simple_type(value, to_type)
|
37
|
+
if to_type == Integer
|
38
|
+
Integer(value)
|
39
|
+
elsif [Float, String].include?(to_type)
|
40
|
+
Kernel.send(to_type.to_s.to_sym, value)
|
41
|
+
elsif to_type.respond_to? :parse
|
42
|
+
to_type.parse(value)
|
43
|
+
else
|
44
|
+
raise_unknown_type(to_type)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_composite_type(value, to_type)
|
49
|
+
if to_type == Array
|
50
|
+
value.split(',')
|
51
|
+
elsif to_type == Hash
|
52
|
+
Hash[value.split(',').map { |item| item.split(':') }]
|
53
|
+
else
|
54
|
+
raise_unknown_type(to_type)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_boolean(value)
|
59
|
+
if value.to_s.casecmp('false').zero?
|
60
|
+
false
|
61
|
+
elsif value.to_s.casecmp('true').zero?
|
62
|
+
true
|
63
|
+
else
|
64
|
+
raise_with_invalid_type(value, Boolean)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def raise_with_invalid_type(value, type)
|
69
|
+
raise ValidateMyRoutes::Errors::InvalidTypeError,
|
70
|
+
"'#{value}' is not a valid '#{type}'"
|
71
|
+
end
|
72
|
+
|
73
|
+
def raise_unknown_type(type)
|
74
|
+
raise ValidateMyRoutes::Errors::InvalidTypeError,
|
75
|
+
"don't know how to convert type '#{type}'"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
# Helper functions to provide a DSL for creating validation rules
|
4
|
+
module Macros
|
5
|
+
# Define all parameters validation
|
6
|
+
#
|
7
|
+
# validate do |params|
|
8
|
+
# params.key? 'some_parameter_name'
|
9
|
+
# end
|
10
|
+
def validate(&block)
|
11
|
+
define_method(:validate, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Customize validation rule description
|
15
|
+
#
|
16
|
+
# description do
|
17
|
+
# 'this is my custom validation rule description'
|
18
|
+
# end
|
19
|
+
def description(&block)
|
20
|
+
define_method(:description, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Customize message returned when validation fails for all parameters
|
24
|
+
#
|
25
|
+
# failure_message do |params|
|
26
|
+
# "oh no! validation failed for #{params}"
|
27
|
+
# end
|
28
|
+
def failure_message(&block)
|
29
|
+
define_method(:failure_message, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Customize message returned when opposite rule validation fails (not of type A)
|
33
|
+
#
|
34
|
+
# failure_message_when_negated do |params|
|
35
|
+
# "oh no! validation failed for #{params}, but it was not expected"
|
36
|
+
# end
|
37
|
+
def failure_message_when_negated(&block)
|
38
|
+
define_method(:failure_message_when_negated, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Customize http status code of the failure
|
42
|
+
#
|
43
|
+
# failure_code do |in_path|
|
44
|
+
# in_path ? 404 : 400
|
45
|
+
# end
|
46
|
+
def failure_code(&block)
|
47
|
+
define_method(:failure_code, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
# Helper functions to provide a DSL for creating validation rules
|
4
|
+
module RulesCombinators
|
5
|
+
# Negate the rule to validate opposite expectation
|
6
|
+
#
|
7
|
+
# is_an_integer = of_type(Integer)
|
8
|
+
# is_not_an_integer = of_type(Integer).negate
|
9
|
+
def negate
|
10
|
+
ValidateMyRoutes::ValidationRules.not self
|
11
|
+
end
|
12
|
+
|
13
|
+
# Chain rule with another one to perform both validations
|
14
|
+
# Note that if first rule fails validation, second is ignored
|
15
|
+
#
|
16
|
+
# required.and of_type(Integer)
|
17
|
+
def and(other_rule)
|
18
|
+
ValidateMyRoutes::ValidationRules.and(self, other_rule)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Chain rule with another one to perform one or another validations
|
22
|
+
# Note that second validation will be performed only if first fails
|
23
|
+
#
|
24
|
+
# eql('all').or of_type(Integer)
|
25
|
+
def or(other_rule)
|
26
|
+
ValidateMyRoutes::ValidationRules.or(self, other_rule)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative 'validation_rule'
|
2
|
+
|
3
|
+
require_relative 'rules/compound'
|
4
|
+
require_relative 'rules/anything'
|
5
|
+
require_relative 'rules/comparable'
|
6
|
+
require_relative 'rules/conditional'
|
7
|
+
require_relative 'rules/of_type'
|
8
|
+
require_relative 'rules/required'
|
9
|
+
require_relative 'rules/transforms'
|
10
|
+
require_relative 'rules/enum'
|
11
|
+
require_relative 'rules/all_parameters'
|
12
|
+
|
13
|
+
module ValidateMyRoutes
|
14
|
+
module Validate
|
15
|
+
# Module provides methods to validate if rule is a rule and if it can be used for single
|
16
|
+
# or all parameters validation.
|
17
|
+
module Rules
|
18
|
+
class << self
|
19
|
+
REQUIRED_RULE_METHODS = %i[validate! description rule_type].freeze
|
20
|
+
|
21
|
+
def single_param_rule?(rule)
|
22
|
+
validation_rule?(rule) && %i[single_param general].include?(rule.rule_type)
|
23
|
+
end
|
24
|
+
|
25
|
+
def all_params_rule?(rule)
|
26
|
+
validation_rule?(rule) && %i[all_params general].include?(rule.rule_type)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Validate that rule can be used for single parameter validation
|
30
|
+
#
|
31
|
+
# Example:
|
32
|
+
#
|
33
|
+
# Rules.validate_single_param_rule! required(:q) # => throws an exception
|
34
|
+
def validate_single_param_rule!(rule)
|
35
|
+
return if Rules.single_param_rule?(rule)
|
36
|
+
raise ValidateMyRoutes::Errors::UnsupportedRuleError,
|
37
|
+
"rule #{rule} must implement #{REQUIRED_RULE_METHODS.join(', ')} " \
|
38
|
+
'and be either :generic or :single_param rule type.'
|
39
|
+
end
|
40
|
+
|
41
|
+
# Validate that rule can be used for all parameters validation
|
42
|
+
#
|
43
|
+
# Example:
|
44
|
+
#
|
45
|
+
# Rules.validate_all_params_rule! of_type(Integer) # => throws an exception
|
46
|
+
def validate_all_params_rule!(rule)
|
47
|
+
return if Rules.all_params_rule?(rule)
|
48
|
+
raise ValidateMyRoutes::Errors::UnsupportedRuleError,
|
49
|
+
"rule #{rule} must implement #{REQUIRED_RULE_METHODS.join(', ')} " \
|
50
|
+
'and be either :generic or :all_params rule type.'
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def validation_rule?(rule)
|
56
|
+
REQUIRED_RULE_METHODS.all? { |method_name| rule.respond_to? method_name }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Validation rules that designed to be used for validating all parameters
|
5
|
+
# in the route.
|
6
|
+
#
|
7
|
+
# For example if we need to allow specifying "all" or "search" criteria,
|
8
|
+
# but not both at the same time.
|
9
|
+
module AllParameters
|
10
|
+
ValidateMyRoutes::ValidationRules.def_all_params_validator :only_one_of do |names|
|
11
|
+
raise Errors::MissusedRuleError, 'names must be an array' unless names.is_a? Array
|
12
|
+
|
13
|
+
validate do |params|
|
14
|
+
present_parameters_count = names.count { |name| params.key? name.to_s }
|
15
|
+
present_parameters_count <= 1
|
16
|
+
end
|
17
|
+
|
18
|
+
description { "only one of <#{names.join(', ')}> parameters" }
|
19
|
+
|
20
|
+
failure_message do |actual|
|
21
|
+
"was expected to have only one of <#{names.join(', ')}> parameters, " \
|
22
|
+
"but <#{actual.keys.join(', ')}> #{actual.size > 1 ? 'were' : 'was'} provided"
|
23
|
+
end
|
24
|
+
|
25
|
+
failure_message_when_negated do |actual|
|
26
|
+
"was expected to have all of <#{names.join(', ')}> parameters, " \
|
27
|
+
"but <#{actual.keys.join(', ')}> #{actual.size > 1 ? 'were' : 'was'} provided"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ValidateMyRoutes::ValidationRules.def_all_params_validator :exactly_one_of do |names|
|
32
|
+
raise Errors::MissusedRuleError, 'names must be an array' unless names.is_a? Array
|
33
|
+
|
34
|
+
validate do |params|
|
35
|
+
present_parameters_count = names.count { |name| params.key? name.to_s }
|
36
|
+
present_parameters_count == 1
|
37
|
+
end
|
38
|
+
|
39
|
+
description { "exactly one of <#{names.join(', ')}> parameters" }
|
40
|
+
|
41
|
+
failure_message do |actual|
|
42
|
+
"was expected to have exactly one of <#{names.join(', ')}> parameters, " \
|
43
|
+
"but <#{actual.keys.join(', ')}> #{actual.size > 1 ? 'were' : 'was'} provided"
|
44
|
+
end
|
45
|
+
|
46
|
+
failure_message_when_negated do |actual|
|
47
|
+
"was expected to have none or more than one of <#{names.join(', ')}>, " \
|
48
|
+
"but <#{actual.keys.join(', ')}> #{actual.size > 1 ? 'were' : 'was'} provided"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ValidateMyRoutes::ValidationRules.def_all_params_validator :at_least_one_of do |names|
|
53
|
+
raise Errors::MissusedRuleError, 'names must be an array' unless names.is_a? Array
|
54
|
+
|
55
|
+
validate do |params|
|
56
|
+
present_parameters_count = names.count { |name| params.key? name.to_s }
|
57
|
+
present_parameters_count >= 1
|
58
|
+
end
|
59
|
+
|
60
|
+
description { "at least one of <#{names.join(', ')}> parameters" }
|
61
|
+
|
62
|
+
failure_message do |actual|
|
63
|
+
"was expected to have at least one of <#{names.join(', ')}> parameters, " \
|
64
|
+
"but <#{actual.keys.join(', ')}> #{actual.size > 1 ? 'were' : 'was'} provided"
|
65
|
+
end
|
66
|
+
|
67
|
+
failure_message_when_negated do |actual|
|
68
|
+
"was expected to have none of <#{names.join(', ')}>, " \
|
69
|
+
"but <#{actual.keys.join(', ')}> #{actual.size > 1 ? 'were' : 'was'} provided"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Always successful validation rule
|
5
|
+
module Anything
|
6
|
+
ValidateMyRoutes::ValidationRules.def_validation_rule :anything do
|
7
|
+
validate { |*_| true }
|
8
|
+
description { 'anything' }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# List of comparison rules
|
5
|
+
module Comparable
|
6
|
+
VR = ValidateMyRoutes::ValidationRules
|
7
|
+
|
8
|
+
VR.def_single_param_validator :eql do |expected|
|
9
|
+
validate { |actual, _| actual == expected }
|
10
|
+
description { "equal to <#{expected}>" }
|
11
|
+
failure_message do |actual, name|
|
12
|
+
"was expected #{name} parameter to equal <#{expected}>, but was <#{actual}>"
|
13
|
+
end
|
14
|
+
failure_message_when_negated do |actual, name|
|
15
|
+
"was expected #{name} parameter to not equal <#{expected}>, but was <#{actual}>"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
VR.def_single_param_validator :greater_than do |expected|
|
20
|
+
validate { |actual, _| actual > expected }
|
21
|
+
description { "greater than <#{expected}>" }
|
22
|
+
failure_message do |actual, name|
|
23
|
+
"was expected #{name} parameter to be greater than <#{expected}>, but was <#{actual}>"
|
24
|
+
end
|
25
|
+
failure_message_when_negated do |actual, name|
|
26
|
+
"was expected #{name} parameter to be less than or equal to <#{expected}>, " \
|
27
|
+
"but was <#{actual}>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
VR.def_single_param_validator :greater_than_or_equal_to do |expected|
|
32
|
+
validate { |actual, _| actual >= expected }
|
33
|
+
description { "greater than or equal to <#{expected}>" }
|
34
|
+
failure_message do |actual, name|
|
35
|
+
"was expected #{name} parameter to be greater than or equal to <#{expected}>, " \
|
36
|
+
"but was <#{actual}>"
|
37
|
+
end
|
38
|
+
failure_message_when_negated do |actual, name|
|
39
|
+
"was expected #{name} parameter to be less than <#{expected}>, but was <#{actual}>"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
VR.def_single_param_validator :less_than do |expected|
|
44
|
+
validate { |actual, _| actual < expected }
|
45
|
+
description { "less than <#{expected}>" }
|
46
|
+
failure_message do |actual, name|
|
47
|
+
"was expected #{name} parameter to be less than <#{expected}>, but was <#{actual}>"
|
48
|
+
end
|
49
|
+
failure_message_when_negated do |actual, name|
|
50
|
+
"was expected #{name} parameter to be greater than or equal to <#{expected}>, " \
|
51
|
+
"but was <#{actual}>"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
VR.def_single_param_validator :less_than_or_equal_to do |expected|
|
56
|
+
validate { |actual, _| actual <= expected }
|
57
|
+
description { "less than or equal to <#{expected}>" }
|
58
|
+
failure_message do |actual, name|
|
59
|
+
"was expected #{name} parameter to be less than or equal to <#{expected}>, " \
|
60
|
+
"but was <#{actual}>"
|
61
|
+
end
|
62
|
+
failure_message_when_negated do |actual, name|
|
63
|
+
"was expected #{name} parameter to be greater than <#{expected}>, but was <#{actual}>"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
VR.def_single_param_validator :between do |min, max|
|
68
|
+
validate { |actual, _| actual >= min && actual <= max }
|
69
|
+
description { "between <#{min}> and <#{max}>" }
|
70
|
+
failure_message do |actual, name|
|
71
|
+
"was expected #{name} parameter to be between <#{min}> and <#{max}>, " \
|
72
|
+
"but was <#{actual}>"
|
73
|
+
end
|
74
|
+
failure_message_when_negated do |actual, name|
|
75
|
+
"was expected #{name} parameter to be less than <#{min}> or greater than <#{max}>, " \
|
76
|
+
"but was <#{actual}>"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Rules combinators
|
5
|
+
# TODO: add validations to the rules before combining them
|
6
|
+
module Compound
|
7
|
+
ValidateMyRoutes::ValidationRules.def_validation_rule :not do |rule|
|
8
|
+
validate do |*args|
|
9
|
+
begin
|
10
|
+
!check(rule, *args)
|
11
|
+
rescue Errors::ValidationError
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
failure_message { |*args| rule.failure_message_when_negated(*args) }
|
17
|
+
failure_message_when_negated { |*args| rule.failure_message(*args) }
|
18
|
+
description { "NOT #{rule.description}" }
|
19
|
+
failure_code { |*args| rule.failure_code(*args) }
|
20
|
+
end
|
21
|
+
|
22
|
+
ValidateMyRoutes::ValidationRules.def_validation_rule :and do |first_rule, second_rule|
|
23
|
+
validate { |*args| check(first_rule, *args) && check(second_rule, *args) }
|
24
|
+
description { "(#{first_rule.description} AND #{second_rule.description})" }
|
25
|
+
end
|
26
|
+
|
27
|
+
ValidateMyRoutes::ValidationRules.def_validation_rule :or do |first_rule, second_rule|
|
28
|
+
validate do |*args|
|
29
|
+
begin
|
30
|
+
check(first_rule, *args) || check(second_rule, *args)
|
31
|
+
rescue Errors::ValidationError
|
32
|
+
check(second_rule, *args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
description { "(#{first_rule.description} OR #{second_rule.description})" }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Validation rule that on failure instruct Sinatra to search for another route instead of
|
5
|
+
# failing with validation error
|
6
|
+
module Conditional
|
7
|
+
ValidateMyRoutes::ValidationRules.def_validation_rule :conditional do |rule|
|
8
|
+
validate do |*args|
|
9
|
+
begin
|
10
|
+
check(rule, *args)
|
11
|
+
rescue Errors::ValidationError => error
|
12
|
+
raise Errors::ConditionalValidationError.new(error.message, error.status_code)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
description { "conditional, #{rule.description}" }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Always successful validation rule
|
5
|
+
module Enum
|
6
|
+
ValidateMyRoutes::ValidationRules.def_single_param_validator :from_enum do |values|
|
7
|
+
unless values.respond_to? :include?
|
8
|
+
raise Errors::MissusedRuleError, 'from_enum rule requires #include? method on ' \
|
9
|
+
'expectation'
|
10
|
+
end
|
11
|
+
validate { |actual, _| values.include? actual }
|
12
|
+
failure_message do |actual, name|
|
13
|
+
"parameter <#{name}> was expected to have one of following values: " \
|
14
|
+
"<#{values.join ', '}>, but was <#{actual}>"
|
15
|
+
end
|
16
|
+
description { "of enum type with values: #{values.join(', ')}" }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative '../convert_to_type'
|
2
|
+
|
3
|
+
module ValidateMyRoutes
|
4
|
+
module Validate
|
5
|
+
module Rules
|
6
|
+
# Rule to validate type of parameter
|
7
|
+
module OfType
|
8
|
+
ValidateMyRoutes::ValidationRules.def_single_param_validator :of_type do |typ|
|
9
|
+
validate do |actual, _|
|
10
|
+
begin
|
11
|
+
ConvertToType.convert_to_type(actual, typ)
|
12
|
+
true
|
13
|
+
rescue ValidateMyRoutes::Errors::InvalidTypeError
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
description { "of a type <#{typ}>" }
|
19
|
+
|
20
|
+
failure_message do |actual, name|
|
21
|
+
"was expected #{name} parameter to be of a type <#{typ}>, but was <#{actual}>"
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message_when_negated do |actual, name|
|
25
|
+
"was expected #{name} parameter to not be of a type <#{typ}>, but was <#{actual}>"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Validation rule that fails if parameter was not provided
|
5
|
+
module Required
|
6
|
+
ValidateMyRoutes::ValidationRules.def_all_params_validator :required do |parameter_name|
|
7
|
+
validate { |params| params.key? parameter_name.to_s }
|
8
|
+
description { "parameter <#{parameter_name}> is required" }
|
9
|
+
failure_message { |_| "parameter <#{parameter_name}> was expected to be present" }
|
10
|
+
failure_message_when_negated do |_|
|
11
|
+
"parameter <#{parameter_name}> was expected not to be present"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ValidateMyRoutes
|
2
|
+
module Validate
|
3
|
+
module Rules
|
4
|
+
# Rules that perform transformation of value before sending it to another rule
|
5
|
+
module Transforms
|
6
|
+
ValidateMyRoutes::ValidationRules.def_single_param_validator :value_as do |typ, rule|
|
7
|
+
validate do |actual, name|
|
8
|
+
begin
|
9
|
+
converted_value = ConvertToType.convert_to_type(actual, typ)
|
10
|
+
check(rule, converted_value, name)
|
11
|
+
rescue ValidateMyRoutes::Errors::InvalidTypeError
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
description { rule.description }
|
17
|
+
|
18
|
+
failure_message do |actual, name|
|
19
|
+
"was expected #{name} parameter to be of type <#{typ}>, but was <#{actual}>"
|
20
|
+
end
|
21
|
+
|
22
|
+
failure_message_when_negated do |_, _|
|
23
|
+
# TODO: make sure that not(value_as(...)) can not be used instead of failing here
|
24
|
+
raise Errors::MissusedRuleError, 'value_as does not support negate operation'
|
25
|
+
end
|
26
|
+
|
27
|
+
failure_code { |*args| rule.failure_code(*args) }
|
28
|
+
end
|
29
|
+
|
30
|
+
ValidateMyRoutes::ValidationRules.def_validation_rule :transform do |transformation, rule|
|
31
|
+
description { rule.description }
|
32
|
+
validate do |*args|
|
33
|
+
if args.size == 2
|
34
|
+
# this means single parameter validation with value and name
|
35
|
+
check(rule, transformation.call(args[0]), args[1])
|
36
|
+
elsif args.size == 1
|
37
|
+
# this means all parameters validation with value only
|
38
|
+
check(rule, transformation.call(args[0]))
|
39
|
+
else
|
40
|
+
raise Errors::MissusedRuleError, "Received #{args.size} instead of 1 or 2"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
failure_message { |*args| rule.failure_message(*args) }
|
44
|
+
failure_message_when_negated { |*args| rule.failure_message_when_negated(*args) }
|
45
|
+
failure_code { |*args| rule.failure_code(*args) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require_relative 'mixins/macros'
|
2
|
+
require_relative 'mixins/rules_combinators'
|
3
|
+
|
4
|
+
module ValidateMyRoutes
|
5
|
+
module Validate
|
6
|
+
# ValidationRule is a base class for all rules
|
7
|
+
class ValidationRule
|
8
|
+
# Add DSL support for declarations in constructor
|
9
|
+
extend Macros
|
10
|
+
include RulesCombinators
|
11
|
+
|
12
|
+
attr_reader :rule_type
|
13
|
+
|
14
|
+
def initialize(rule_name, rule_type, *expected, declarations)
|
15
|
+
self.rule_name = rule_name
|
16
|
+
self.rule_type = rule_type
|
17
|
+
self.app = nil # this is a Sinatra application instance
|
18
|
+
singleton_class.class_exec(*expected, &declarations)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Current method can be used for validation
|
22
|
+
def validate!(app, value, path_param, *args)
|
23
|
+
# save current Sinatra app instance for method lookup on it
|
24
|
+
self.app = app
|
25
|
+
|
26
|
+
self.value = value
|
27
|
+
self.path_param = path_param == true
|
28
|
+
|
29
|
+
validate(value, *args) || fail_validation(failure_message(value, *args))
|
30
|
+
rescue Errors::ValidationError
|
31
|
+
# validation failed, so just re-raise an error to buble it up to the root
|
32
|
+
# re-raising is needed in order to catch all other exceptions to wrap them in
|
33
|
+
# special error
|
34
|
+
raise
|
35
|
+
rescue => ex # rubocop:disable Style/RescueStandardError
|
36
|
+
# unexpected exception happened in validation block, so we should wrap it in special error
|
37
|
+
raise Errors::ValidationRaisedAnExceptionError.new(ex, failure_code(path_param?))
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate(*_args)
|
41
|
+
raise Errors::MissusedRuleError, 'validate method not implemented'
|
42
|
+
end
|
43
|
+
|
44
|
+
def description
|
45
|
+
rule_name.to_s.capitalize.tr('_', ' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def failure_code(in_path)
|
49
|
+
in_path ? 404 : 400
|
50
|
+
end
|
51
|
+
|
52
|
+
def failure_message(*args)
|
53
|
+
if args.size == 1
|
54
|
+
"parameters were expected to satisfy: #{description} but were <#{args[0]}>"
|
55
|
+
elsif args.size == 2
|
56
|
+
"parameter #{args[1]} was expected to satisfy: #{description} but was <#{args[0]}>"
|
57
|
+
else
|
58
|
+
raise Errors::MissusedRuleError, "failure_message method called with #{args.size} " \
|
59
|
+
'arguments'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def failure_message_when_negated(*args)
|
64
|
+
if args.size == 1
|
65
|
+
"parameters were expected not to satisfy: #{description} but were <#{args[0]}>"
|
66
|
+
elsif args.size == 2
|
67
|
+
"parameter #{args[1]} was expected not to satisfy: #{description} but was <#{args[0]}>"
|
68
|
+
else
|
69
|
+
raise Errors::MissusedRuleError, 'failure_message_when_negated method called with ' \
|
70
|
+
"#{args.size} arguments"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Expand method lookup to the application scope
|
75
|
+
def method_missing(method_name, *args, &block)
|
76
|
+
app && app.respond_to?(method_name) ? app.send(method_name, *args, &block) : super
|
77
|
+
end
|
78
|
+
|
79
|
+
def respond_to_missing?(method_name, include_private = false)
|
80
|
+
super || app.respond_to?(method_name) || super
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
attr_accessor :app, :value, :path_param, :rule_name
|
86
|
+
attr_writer :rule_type
|
87
|
+
|
88
|
+
# Helper method to perform validation of other rules inside validation block
|
89
|
+
#
|
90
|
+
# validate do |params|
|
91
|
+
# # make use of built in validation rules in custom validations
|
92
|
+
# check(of_type(Integer), params[:id], :id)
|
93
|
+
# # or validate all parameters
|
94
|
+
# check(required(:id), params)
|
95
|
+
# end
|
96
|
+
def check(rule, value, *args)
|
97
|
+
if args.empty?
|
98
|
+
ValidateMyRoutes::Validate::Rules.validate_all_params_rule! rule
|
99
|
+
elsif args.size == 1
|
100
|
+
ValidateMyRoutes::Validate::Rules.validate_single_param_rule! rule
|
101
|
+
else
|
102
|
+
raise Errors::MissusedRuleError, "check method called with #{args.size} arguments"
|
103
|
+
end
|
104
|
+
|
105
|
+
rule.validate!(app, value, path_param?, *args)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Helper method to fail validation
|
109
|
+
#
|
110
|
+
# validate do |params|
|
111
|
+
# fail_validation 'no!' if params.size > 1
|
112
|
+
# end
|
113
|
+
def fail_validation(message, code = nil)
|
114
|
+
code ||= failure_code(path_param?)
|
115
|
+
raise Errors::ValidationError.new(message, code)
|
116
|
+
end
|
117
|
+
|
118
|
+
def path_param?
|
119
|
+
path_param
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative './validate/validation_rule'
|
2
|
+
|
3
|
+
module ValidateMyRoutes
|
4
|
+
# Mixin to add custom rules to the application.
|
5
|
+
#
|
6
|
+
# To create custom rule you can extend your class with ValidationRules:
|
7
|
+
# extend ValidateMyRoutes::ValidationRules
|
8
|
+
module ValidationRules
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def def_single_param_validator(name, &declarations)
|
12
|
+
def_validation_rule name, :single_param, &declarations
|
13
|
+
end
|
14
|
+
|
15
|
+
def def_all_params_validator(name, &declarations)
|
16
|
+
def_validation_rule name, :all_params, &declarations
|
17
|
+
end
|
18
|
+
|
19
|
+
def def_validation_rule(name, typ = :general, &declarations)
|
20
|
+
raise Errors::MissingValidationDeclarationBlock unless block_given?
|
21
|
+
raise Errors::ValidationRuleNamingConflict, name.to_sym if respond_to? name.to_sym
|
22
|
+
|
23
|
+
rule = ->(*expected) { Validate::ValidationRule.new(name, typ, *expected, declarations) }
|
24
|
+
|
25
|
+
define_method(name, rule)
|
26
|
+
define_singleton_method(name, rule)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: validate_my_routes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Workday, Ltd.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack-test
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sinatra
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: ValidateMyRoutes provides a way to annotate Sinatra routes and validate
|
98
|
+
parameters before executing the route
|
99
|
+
email:
|
100
|
+
- prd.eng.os@workday.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- lib/validate_my_routes.rb
|
106
|
+
- lib/validate_my_routes/errors.rb
|
107
|
+
- lib/validate_my_routes/validatable.rb
|
108
|
+
- lib/validate_my_routes/validate.rb
|
109
|
+
- lib/validate_my_routes/validate/convert_to_type.rb
|
110
|
+
- lib/validate_my_routes/validate/mixins/macros.rb
|
111
|
+
- lib/validate_my_routes/validate/mixins/rules_combinators.rb
|
112
|
+
- lib/validate_my_routes/validate/rules.rb
|
113
|
+
- lib/validate_my_routes/validate/rules/all_parameters.rb
|
114
|
+
- lib/validate_my_routes/validate/rules/anything.rb
|
115
|
+
- lib/validate_my_routes/validate/rules/comparable.rb
|
116
|
+
- lib/validate_my_routes/validate/rules/compound.rb
|
117
|
+
- lib/validate_my_routes/validate/rules/conditional.rb
|
118
|
+
- lib/validate_my_routes/validate/rules/enum.rb
|
119
|
+
- lib/validate_my_routes/validate/rules/of_type.rb
|
120
|
+
- lib/validate_my_routes/validate/rules/required.rb
|
121
|
+
- lib/validate_my_routes/validate/rules/transforms.rb
|
122
|
+
- lib/validate_my_routes/validate/validation_rule.rb
|
123
|
+
- lib/validate_my_routes/validation_rules.rb
|
124
|
+
- lib/validate_my_routes/version.rb
|
125
|
+
homepage: https://github.com/Workday/validate_my_routes
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.4.8
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: A simple gem to validate Sinatra routes
|
149
|
+
test_files: []
|