otoroshi 0.0.8 → 0.0.9
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 +4 -4
- data/lib/otoroshi.rb +4 -5
- data/lib/otoroshi/exceptions.rb +68 -52
- data/lib/otoroshi/initializer.rb +71 -25
- data/lib/otoroshi/sanctuary.rb +80 -113
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e8733049cbcd069bfdb9ba26863300e6b5547f67dae40ead37c757536f60d3e2
|
|
4
|
+
data.tar.gz: 1e92ac383197980ba7e7579236525989a627dc9517ca3112e062a5fd5e09fc5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 54fd97b58be1a21e910d03fafa2c55bced96d549030c5014254674fbaec98f69633b9a0d9a698624f3d09259275920ee2f23bccc7a2425427547da20592b25a7
|
|
7
|
+
data.tar.gz: d9116888ba124a752fddbc1b31e1f11733931d4bd946beb7c9c159e43a60847da0337da32cb4172d4cbf25e44881e599478d97ef5405bd79c1507d08a2dbcc85
|
data/lib/otoroshi.rb
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'otoroshi/sanctuary'
|
|
4
|
-
require_relative 'otoroshi/exceptions'
|
|
5
|
-
|
|
6
3
|
# Otoroshi entry-point
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
module Otoroshi
|
|
5
|
+
require_relative 'otoroshi/sanctuary'
|
|
6
|
+
require_relative 'otoroshi/exceptions'
|
|
7
|
+
end
|
data/lib/otoroshi/exceptions.rb
CHANGED
|
@@ -1,73 +1,89 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative './initializer'
|
|
4
|
+
|
|
3
5
|
module Otoroshi
|
|
4
6
|
class Error < StandardError; end
|
|
5
7
|
|
|
6
|
-
# Manages errors raised when value
|
|
7
|
-
class
|
|
8
|
-
# Initialize an error
|
|
9
|
-
#
|
|
8
|
+
# Manages errors raised when value is not an instance of the expected class
|
|
9
|
+
class TypeError < Error
|
|
10
10
|
# @param property [Symbol] name of the property
|
|
11
11
|
# @param type [Class] class to match
|
|
12
|
-
# @
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if collection
|
|
17
|
-
":#{property} contains elements that are not instances of #{expected_type}"
|
|
18
|
-
else
|
|
19
|
-
":#{property} is not an instance of #{expected_type}"
|
|
20
|
-
end
|
|
21
|
-
super(msg)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Manages errors raised when value should be an collection
|
|
26
|
-
class NotAnArray < Error
|
|
27
|
-
# Initialize an error
|
|
28
|
-
#
|
|
29
|
-
# @param property [Symbol] name of the property
|
|
30
|
-
def initialize(property)
|
|
31
|
-
msg = ":#{property} is not an array"
|
|
32
|
-
super(msg)
|
|
12
|
+
# @example
|
|
13
|
+
# ":number is not an instance of Integer"
|
|
14
|
+
def initialize(property, type)
|
|
15
|
+
super ":#{property} is not an instance of #{type}"
|
|
33
16
|
end
|
|
34
17
|
end
|
|
35
18
|
|
|
36
|
-
# Manages errors raised when value is not accepted (not
|
|
37
|
-
class
|
|
38
|
-
# Initialize an error
|
|
39
|
-
#
|
|
19
|
+
# Manages errors raised when value is not accepted (not in the "one_of")
|
|
20
|
+
class OneOfError < Error
|
|
40
21
|
# @param property [Symbol] name of the property
|
|
41
|
-
# @param
|
|
42
|
-
# @
|
|
43
|
-
|
|
22
|
+
# @param values [Array] accepted values
|
|
23
|
+
# @example
|
|
24
|
+
# ":fruit is not in [:apple, :pear]"
|
|
25
|
+
def initialize(property, values)
|
|
44
26
|
# reintegrate the colon for symbols which is lost during interpolation
|
|
45
27
|
to_s = ->(v) { v.is_a?(Symbol) ? ":#{v}" : v }
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if collection
|
|
49
|
-
":#{property} contains elements that are not included in [#{accepted_values_list}]"
|
|
50
|
-
else
|
|
51
|
-
":#{property} is not included in [#{accepted_values_list}]"
|
|
52
|
-
end
|
|
53
|
-
super(msg)
|
|
28
|
+
list = values.map { |v| to_s.call(v) }.join(', ')
|
|
29
|
+
super ":#{property} is not in [#{list}]"
|
|
54
30
|
end
|
|
55
31
|
end
|
|
56
32
|
|
|
57
33
|
# Manages errors raised when value does not pass the assertion
|
|
58
|
-
class
|
|
59
|
-
# Initialize an error
|
|
60
|
-
#
|
|
34
|
+
class AssertError < Error
|
|
61
35
|
# @param property [Symbol] name of the property
|
|
62
|
-
# @
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
36
|
+
# @example
|
|
37
|
+
# ":number does not respect the assertion"
|
|
38
|
+
def initialize(property)
|
|
39
|
+
super ":#{property} does not respect the assertion"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module Collection
|
|
44
|
+
# Manages errors raised when value should be an collection
|
|
45
|
+
class ArrayError < Error
|
|
46
|
+
# @param property [Symbol] name of the property
|
|
47
|
+
# @example
|
|
48
|
+
# ":numbers is not an array"
|
|
49
|
+
def initialize(property)
|
|
50
|
+
super ":#{property} is not an array"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Manages errors raised when at least one element of the collection is not an instance of the expected class
|
|
55
|
+
class TypeError < Error
|
|
56
|
+
# @param property [Symbol] name of the property
|
|
57
|
+
# @param type [Class] class to match
|
|
58
|
+
# @example
|
|
59
|
+
# ":numbers contains elements that are not instances of Integer"
|
|
60
|
+
def initialize(property, type)
|
|
61
|
+
super ":#{property} contains elements that are not instances of #{type}"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Manages errors raised when at least one element of the collection is not accepted (not in the "one_of")
|
|
66
|
+
class OneOfError < Error
|
|
67
|
+
# @param property [Symbol] name of the property
|
|
68
|
+
# @param values [Array] accepted values
|
|
69
|
+
# @example
|
|
70
|
+
# ":fruits contains elements that are not in [:apple, :pear]"
|
|
71
|
+
def initialize(property, values)
|
|
72
|
+
# reintegrate the colon for symbols which is lost during interpolation
|
|
73
|
+
to_s = ->(v) { v.is_a?(Symbol) ? ":#{v}" : v }
|
|
74
|
+
list = values.map { |v| to_s.call(v) }.join(', ')
|
|
75
|
+
super ":#{property} contains elements that are not in [#{list}]"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Manages errors raised when value does not pass the assertion
|
|
80
|
+
class AssertError < Error
|
|
81
|
+
# @param property [Symbol] name of the property
|
|
82
|
+
# @example
|
|
83
|
+
# ":numbers contains elements that do not respect the assertion"
|
|
84
|
+
def initialize(property)
|
|
85
|
+
super ":#{property} contains elements that do not respect the assertion"
|
|
86
|
+
end
|
|
71
87
|
end
|
|
72
88
|
end
|
|
73
89
|
end
|
data/lib/otoroshi/initializer.rb
CHANGED
|
@@ -13,9 +13,15 @@ module Otoroshi
|
|
|
13
13
|
#
|
|
14
14
|
# @example
|
|
15
15
|
# <<-RUBY
|
|
16
|
-
# def initialize(
|
|
17
|
-
# self.
|
|
18
|
-
# self.
|
|
16
|
+
# def initialize(number: 0, message:, fruits: [])
|
|
17
|
+
# self.number = number
|
|
18
|
+
# self.message = message
|
|
19
|
+
# self.fruits = fruits
|
|
20
|
+
# bind = self
|
|
21
|
+
# @fruits.singleton_class.send(:define_method, :<<) do |v|
|
|
22
|
+
# bind.send(:"validate_fruits!", [v])
|
|
23
|
+
# push(v)
|
|
24
|
+
# end
|
|
19
25
|
# end
|
|
20
26
|
# RUBY
|
|
21
27
|
def draw(properties)
|
|
@@ -42,7 +48,7 @@ module Otoroshi
|
|
|
42
48
|
# end
|
|
43
49
|
# RUBY
|
|
44
50
|
def draw
|
|
45
|
-
|
|
51
|
+
<<~RUBY
|
|
46
52
|
def initialize(#{initialize_parameters})
|
|
47
53
|
#{initialize_assignments}
|
|
48
54
|
#{initialize_push_singletons}
|
|
@@ -58,8 +64,8 @@ module Otoroshi
|
|
|
58
64
|
#
|
|
59
65
|
# @return [String]
|
|
60
66
|
#
|
|
61
|
-
# @example
|
|
62
|
-
#
|
|
67
|
+
# @example
|
|
68
|
+
# "foo:, bar: 0"
|
|
63
69
|
def initialize_parameters
|
|
64
70
|
parameters =
|
|
65
71
|
properties.map do |key, options|
|
|
@@ -68,23 +74,40 @@ module Otoroshi
|
|
|
68
74
|
parameters.join(', ')
|
|
69
75
|
end
|
|
70
76
|
|
|
71
|
-
#
|
|
77
|
+
# Generates the default value of a parameter depending on options
|
|
72
78
|
#
|
|
73
79
|
# @return [String]
|
|
74
80
|
#
|
|
75
81
|
# @example when nil is allowed and default is set
|
|
76
|
-
#
|
|
82
|
+
# " \"default\""
|
|
77
83
|
# @example when nil is allowed and default is not set
|
|
78
|
-
#
|
|
84
|
+
# " nil"
|
|
79
85
|
# @example when nil is not allowed
|
|
80
|
-
#
|
|
86
|
+
# ""
|
|
81
87
|
def default_parameter_for(options)
|
|
82
88
|
default, allow_nil = options.values_at(:default, :allow_nil)
|
|
83
|
-
if default
|
|
84
|
-
symbol_prefix = default.is_a?(Symbol) ? ':' : ''
|
|
85
|
-
" #{symbol_prefix}#{default}"
|
|
86
|
-
else
|
|
89
|
+
if default.nil?
|
|
87
90
|
allow_nil ? ' nil' : ''
|
|
91
|
+
else
|
|
92
|
+
" #{prefix(default)}#{default}#{suffix(default)}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Generates the characters to put before the value
|
|
97
|
+
# @note it avoids symbol without colon or string without quotes
|
|
98
|
+
# which would be interpreted as methods
|
|
99
|
+
def prefix(default)
|
|
100
|
+
case default
|
|
101
|
+
when Symbol then ':'
|
|
102
|
+
when String then '"'
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Generates the characters to put after the value
|
|
107
|
+
# @note it avoids string without quotes which would be interpreted as method
|
|
108
|
+
def suffix(default)
|
|
109
|
+
case default
|
|
110
|
+
when String then '"'
|
|
88
111
|
end
|
|
89
112
|
end
|
|
90
113
|
|
|
@@ -93,44 +116,67 @@ module Otoroshi
|
|
|
93
116
|
# @return [String]
|
|
94
117
|
#
|
|
95
118
|
# @example Given properties { foo: { allow_nil: false, default: nil }, { allow_nil: true, default: 0 } }
|
|
96
|
-
#
|
|
119
|
+
# <<-RUBY
|
|
120
|
+
# self.foo = foo
|
|
121
|
+
# self.bar = bar
|
|
122
|
+
# RUBY
|
|
97
123
|
def initialize_assignments
|
|
98
124
|
assignments =
|
|
99
125
|
properties.keys.map do |name|
|
|
100
126
|
"self.#{name} = #{name}"
|
|
101
127
|
end
|
|
102
|
-
assignments.join("\n")
|
|
128
|
+
assignments.join("\n ")
|
|
103
129
|
end
|
|
104
130
|
|
|
105
131
|
# Generates push singleton for each array property
|
|
106
132
|
#
|
|
107
133
|
# @return [String]
|
|
134
|
+
#
|
|
135
|
+
# @example
|
|
136
|
+
# <<-RUBY
|
|
137
|
+
# bind = self
|
|
138
|
+
# @fruits.singleton_class.send(:define_method, :<<) do |v|
|
|
139
|
+
# bind.send(:"validate_fruits!", [v])
|
|
140
|
+
# push(v)
|
|
141
|
+
# end
|
|
142
|
+
# @numbers.singleton_class.send(:define_method, :<<) do |v|
|
|
143
|
+
# bind.send(:"validate_numbers!", [v])
|
|
144
|
+
# push(v)
|
|
145
|
+
# end
|
|
146
|
+
# RUBY
|
|
108
147
|
def initialize_push_singletons
|
|
109
148
|
collections =
|
|
110
149
|
properties.select do |_, options|
|
|
111
150
|
options[:type].is_a?(Array) || options[:type] == Array
|
|
112
151
|
end
|
|
152
|
+
return if collections.empty?
|
|
153
|
+
|
|
113
154
|
singletons =
|
|
114
155
|
collections.keys.map do |name|
|
|
115
156
|
initialize_push_singleton(name)
|
|
116
157
|
end
|
|
117
|
-
|
|
158
|
+
# assign self to a variable so the instance is accessible from the singleton scope
|
|
159
|
+
['bind = self', singletons.join].join("\n")
|
|
118
160
|
end
|
|
119
161
|
|
|
120
162
|
# Generates singleton on collection instance variable to overide <<
|
|
121
163
|
# so value is validated before being added to the collection
|
|
122
164
|
#
|
|
123
165
|
# @return [String]
|
|
166
|
+
#
|
|
167
|
+
# @example
|
|
168
|
+
# <<-RUBY
|
|
169
|
+
# @fruits.singleton_class.send(:define_method, :<<) do |v|
|
|
170
|
+
# bind.send(:"validate_fruits!", [v])
|
|
171
|
+
# push(v)
|
|
172
|
+
# end
|
|
173
|
+
# RUBY
|
|
124
174
|
def initialize_push_singleton(name)
|
|
125
175
|
<<-RUBY
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
bind.send(:"validate_#{name}_assertion!", [v])
|
|
131
|
-
|
|
132
|
-
push(v)
|
|
133
|
-
end
|
|
176
|
+
@#{name}.singleton_class.send(:define_method, :<<) do |v|
|
|
177
|
+
bind.send(:"validate_#{name}!", [v])
|
|
178
|
+
push(v)
|
|
179
|
+
end
|
|
134
180
|
RUBY
|
|
135
181
|
end
|
|
136
182
|
end
|
data/lib/otoroshi/sanctuary.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require_relative 'initializer'
|
|
4
4
|
|
|
5
5
|
module Otoroshi
|
|
6
|
-
# This module is designed to be
|
|
6
|
+
# This module is designed to be in a class. This will provide
|
|
7
7
|
# the "property" ({Sanctuary::ClassMethods.property}) method for defining class properties.
|
|
8
8
|
#
|
|
9
9
|
# @example
|
|
@@ -45,29 +45,34 @@ module Otoroshi
|
|
|
45
45
|
# property scores, type: [Integer], assert: ->(v) { v >= 0 }, default: []
|
|
46
46
|
def property(name, type = Object, one_of: nil, assert: ->(_) { true }, allow_nil: false, default: nil)
|
|
47
47
|
add_to_properties(name, type, allow_nil, default)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
expected_type = type.is_a?(Array) ? type.first || Object : type
|
|
49
|
+
collection = expected_type == Array || type.is_a?(Array)
|
|
50
|
+
define_validate_type!(name, expected_type, collection, allow_nil)
|
|
51
|
+
define_validate_one_of!(name, collection, one_of, allow_nil)
|
|
51
52
|
define_validate_assertion!(name, collection, assert, allow_nil)
|
|
53
|
+
define_validate!(name)
|
|
52
54
|
define_getter(name)
|
|
53
55
|
define_setter(name)
|
|
56
|
+
puts Initializer.draw(properties)
|
|
54
57
|
class_eval Initializer.draw(properties), __FILE__, __LINE__ + 1
|
|
55
58
|
end
|
|
56
59
|
|
|
57
|
-
#
|
|
60
|
+
# Class properties
|
|
58
61
|
#
|
|
59
62
|
# @return [Hash]
|
|
60
63
|
#
|
|
61
|
-
# @
|
|
64
|
+
# @example
|
|
65
|
+
# {
|
|
66
|
+
# number: { type: Integer, allow_nil: false, default: 0 },
|
|
67
|
+
# message: { type: Integer, allow_nil: true, default: nil }
|
|
68
|
+
# }
|
|
62
69
|
def properties
|
|
63
70
|
{}
|
|
64
71
|
end
|
|
65
72
|
|
|
66
73
|
private
|
|
67
74
|
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
# @return [void]
|
|
75
|
+
# Adds a properties to the {properties}
|
|
71
76
|
def add_to_properties(name, type, allow_nil, default)
|
|
72
77
|
current_state = properties
|
|
73
78
|
current_state[name] = {
|
|
@@ -78,155 +83,123 @@ module Otoroshi
|
|
|
78
83
|
define_singleton_method(:properties) { current_state }
|
|
79
84
|
end
|
|
80
85
|
|
|
81
|
-
# Defines a private method that
|
|
86
|
+
# Defines a private method that validates type condition
|
|
82
87
|
#
|
|
83
|
-
#
|
|
88
|
+
# Given name = :score, type = Integer, allow_nil = false
|
|
84
89
|
#
|
|
85
|
-
# @example
|
|
86
|
-
# define_validate_type!(:score, Integer, false) => def validate_score_type!(value) ...
|
|
87
|
-
# @example Generated method
|
|
88
|
-
# # given name: :score, type: Integer, allow_nil: false
|
|
89
90
|
# def validate_score_type!(value)
|
|
90
91
|
# return if Integer.nil? || false && value.nil?
|
|
91
92
|
# return if value.is_a? Integer
|
|
92
93
|
#
|
|
93
|
-
# raise
|
|
94
|
+
# raise Otoroshi::TypeError, :score, Integer
|
|
94
95
|
# end
|
|
95
96
|
def define_validate_type!(name, type, collection, allow_nil)
|
|
96
|
-
|
|
97
|
-
check_collection = ->(v) { v.is_a?(Array) || raise(Otoroshi::NotAnArray, name) }
|
|
97
|
+
validator = validate_type?(name, type, collection)
|
|
98
98
|
define_method :"validate_#{name}_type!" do |value|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
collection && check_collection.call(value)
|
|
102
|
-
return if lambda.call(value)
|
|
103
|
-
|
|
104
|
-
raise Otoroshi::WrongTypeError.new(name, type, collection: collection)
|
|
99
|
+
allow_nil && value.nil? || validator.call(value)
|
|
105
100
|
end
|
|
106
101
|
private :"validate_#{name}_type!"
|
|
107
102
|
end
|
|
108
103
|
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
# @note params are used for binding in define_method scope
|
|
119
|
-
def type_validation(type)
|
|
120
|
-
if type == Array
|
|
121
|
-
# no expected type for each element, return nil
|
|
122
|
-
->(_) {}
|
|
123
|
-
elsif type.is_a?(Array)
|
|
124
|
-
# get the real expected type
|
|
125
|
-
# e.g. if type is [Integer] then element_type should be Integer
|
|
126
|
-
# e.g. if type is [] then element_type should be Object
|
|
127
|
-
element_type = type.first || Object
|
|
128
|
-
# apply type_validation lambda on each element
|
|
129
|
-
->(v) { v.all? { |e| type_validation(element_type).call(e) } }
|
|
104
|
+
# Lambda that validates (value) respects the type condition
|
|
105
|
+
# @return [Proc]
|
|
106
|
+
def validate_type?(name, type, collection)
|
|
107
|
+
if collection
|
|
108
|
+
# validate each element of (v) is an instance of the type
|
|
109
|
+
lambda do |v|
|
|
110
|
+
v.is_a?(Array) || raise(Otoroshi::Collection::ArrayError, name)
|
|
111
|
+
v.all? { |elt| elt.is_a? type } || raise(Otoroshi::Collection::TypeError.new(name, type))
|
|
112
|
+
end
|
|
130
113
|
else
|
|
131
|
-
#
|
|
132
|
-
->(v) { v.is_a? type }
|
|
114
|
+
# validate (v) is an instance of the type
|
|
115
|
+
->(v) { v.is_a?(type) || raise(Otoroshi::TypeError.new(name, type)) }
|
|
133
116
|
end
|
|
134
117
|
end
|
|
135
118
|
|
|
136
|
-
# Defines a private method that
|
|
119
|
+
# Defines a private method that validates one_of condition
|
|
137
120
|
#
|
|
138
|
-
#
|
|
121
|
+
# Given name = :side, collection = false, one_of = [:left, :right], allow_nil = false
|
|
139
122
|
#
|
|
140
|
-
# @example
|
|
141
|
-
# # given @name = :side
|
|
142
|
-
# define_validate_inclusion!(:side, ...) => def validate_side_type!(value) ...
|
|
143
|
-
# @example Generated method
|
|
144
|
-
# # given name: :side, collection: false, one_of: [:left, :right], allow_nil: false
|
|
145
123
|
# def validate_side_type!(value)
|
|
146
124
|
# return if false && value.nil?
|
|
147
125
|
# return if [:left, :right].include? value
|
|
148
126
|
#
|
|
149
|
-
# raise
|
|
127
|
+
# raise Otoroshi::OneOfError, :side, [:left, :right]
|
|
150
128
|
# end
|
|
151
|
-
def
|
|
152
|
-
validator =
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
allow_nil && value.nil? || validator.call(value)
|
|
156
|
-
end
|
|
157
|
-
else
|
|
158
|
-
define_method(:"validate_#{name}_inclusion!") { |_| }
|
|
129
|
+
def define_validate_one_of!(name, collection, one_of, allow_nil)
|
|
130
|
+
validator = validate_one_of?(name, one_of, collection)
|
|
131
|
+
define_method(:"validate_#{name}_one_of!") do |value|
|
|
132
|
+
allow_nil && value.nil? || validator.call(value)
|
|
159
133
|
end
|
|
160
|
-
private :"validate_#{name}
|
|
134
|
+
private :"validate_#{name}_one_of!"
|
|
161
135
|
end
|
|
162
136
|
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
lambda do |v|
|
|
168
|
-
one_of.include?(v) || raise(Otoroshi::NotAcceptedError.new(name, one_of))
|
|
169
|
-
end
|
|
170
|
-
end
|
|
137
|
+
# Lambda that validates (value) respects the one_of condition
|
|
138
|
+
# @return [Proc]
|
|
139
|
+
def validate_one_of?(name, one_of, collection)
|
|
140
|
+
return ->(_) {} unless one_of
|
|
171
141
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
142
|
+
if collection
|
|
143
|
+
lambda do |v|
|
|
144
|
+
v.all? { |e| one_of.include? e } || raise(Otoroshi::Collection::OneOfError.new(name, one_of))
|
|
145
|
+
end
|
|
146
|
+
else
|
|
147
|
+
lambda do |v|
|
|
148
|
+
one_of.include?(v) || raise(Otoroshi::OneOfError.new(name, one_of))
|
|
149
|
+
end
|
|
178
150
|
end
|
|
179
151
|
end
|
|
180
152
|
|
|
181
|
-
# Defines a private method that
|
|
153
|
+
# Defines a private method that validates assert condition
|
|
182
154
|
#
|
|
183
|
-
#
|
|
155
|
+
# Given name = :score, assert = ->(v) { v >= 0 }, allow_nil = false
|
|
184
156
|
#
|
|
185
|
-
# @example
|
|
186
|
-
# define_validate_assertion!(:score, ...) #=> def validate_score_assertion!(value) ...
|
|
187
|
-
# @example Generated instance method
|
|
188
|
-
# # given name: :score, assert: >(v) { v >= 0 }, allow_nil: false
|
|
189
157
|
# def validate_score_assertion!(value)
|
|
190
158
|
# return if false && value.nil?
|
|
191
159
|
# return if value >= 0
|
|
192
160
|
#
|
|
193
|
-
# raise
|
|
161
|
+
# raise Otoroshi::AssertError, :score
|
|
194
162
|
# end
|
|
195
163
|
def define_validate_assertion!(name, collection, assert, allow_nil)
|
|
196
|
-
validator =
|
|
164
|
+
validator = validate_assert?(name, assert, collection)
|
|
197
165
|
define_method :"validate_#{name}_assertion!" do |value|
|
|
198
166
|
allow_nil && value.nil? || validator.call(value)
|
|
199
167
|
end
|
|
200
168
|
private :"validate_#{name}_assertion!"
|
|
201
169
|
end
|
|
202
170
|
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
171
|
+
# Lambda that validates (value) respects the assert condition
|
|
172
|
+
# @return [Proc]
|
|
173
|
+
def validate_assert?(name, assert, collection)
|
|
174
|
+
if collection
|
|
175
|
+
->(v) { v.all? { |e| instance_exec(e, &assert) } || raise(Otoroshi::Collection::AssertError, name) }
|
|
176
|
+
else
|
|
177
|
+
->(v) { instance_exec(v, &assert) || raise(Otoroshi::AssertError, name) }
|
|
209
178
|
end
|
|
210
179
|
end
|
|
211
180
|
|
|
212
|
-
# Defines a
|
|
181
|
+
# Defines a private method that calls all validations
|
|
182
|
+
#
|
|
183
|
+
# Given name = :score
|
|
213
184
|
#
|
|
214
|
-
#
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
185
|
+
# def validate_score!(value)
|
|
186
|
+
# validate_score_type!(value)
|
|
187
|
+
# validate_score_one_of!(value)
|
|
188
|
+
# validate_score_assert(value)
|
|
189
|
+
# end
|
|
190
|
+
def define_validate!(name)
|
|
191
|
+
define_method :"validate_#{name}!" do |value|
|
|
192
|
+
__send__(:"validate_#{name}_type!", value)
|
|
193
|
+
__send__(:"validate_#{name}_one_of!", value)
|
|
194
|
+
__send__(:"validate_#{name}_assertion!", value)
|
|
219
195
|
end
|
|
196
|
+
private :"validate_#{name}!"
|
|
220
197
|
end
|
|
221
198
|
|
|
222
|
-
# Defines a getter
|
|
199
|
+
# Defines a getter
|
|
223
200
|
#
|
|
224
|
-
#
|
|
201
|
+
# Given name = :score
|
|
225
202
|
#
|
|
226
|
-
# @example
|
|
227
|
-
# define_getter(:score) #=> def score ...
|
|
228
|
-
# @example Generated instance method
|
|
229
|
-
# # given name: :score
|
|
230
203
|
# def score
|
|
231
204
|
# instance_variable_get(@score)
|
|
232
205
|
# end
|
|
@@ -234,14 +207,10 @@ module Otoroshi
|
|
|
234
207
|
define_method(name) { instance_variable_get("@#{name}") }
|
|
235
208
|
end
|
|
236
209
|
|
|
237
|
-
# Defines a setter
|
|
210
|
+
# Defines a setter
|
|
238
211
|
#
|
|
239
|
-
#
|
|
212
|
+
# Given name = :score
|
|
240
213
|
#
|
|
241
|
-
# @example
|
|
242
|
-
# define_setter(:score) #=> def score=(value) ...
|
|
243
|
-
# @example Generated instance method
|
|
244
|
-
# # given name: :score
|
|
245
214
|
# def score=(value)
|
|
246
215
|
# validate_score_type!(value)
|
|
247
216
|
# validate_score!(value)
|
|
@@ -249,9 +218,7 @@ module Otoroshi
|
|
|
249
218
|
# end
|
|
250
219
|
def define_setter(name)
|
|
251
220
|
define_method :"#{name}=" do |value|
|
|
252
|
-
__send__(:"validate_#{name}
|
|
253
|
-
__send__(:"validate_#{name}_inclusion!", value)
|
|
254
|
-
__send__(:"validate_#{name}_assertion!", value)
|
|
221
|
+
__send__(:"validate_#{name}!", value)
|
|
255
222
|
instance_variable_set("@#{name}", value)
|
|
256
223
|
end
|
|
257
224
|
end
|