otoroshi 0.0.3 → 0.0.8
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 +8 -0
- data/lib/otoroshi/exceptions.rb +73 -0
- data/lib/otoroshi/initializer.rb +137 -0
- data/lib/otoroshi/sanctuary.rb +189 -162
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fba1623080c055e87c2055001a7f2370e459b5fe1a28774375cef3dd9e7da802
|
4
|
+
data.tar.gz: 4c01c52a123157e572b4fdcef7c2e7eb6f0cc6ef2162e49237b5a49785708b70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b89127bff4d54b14be27fe723db61e6f0786b7f0f9f6d4df612ed49b3d86d59f1a1df55038178662e5ce247c4b2f6af16b35e05650730d8b9889debd354ed48
|
7
|
+
data.tar.gz: 177fbc07e846a1cb9cbc7b3e595ce5c0878ff153d6293d9e0ccf986745a0b898e3b2a9be144218b97425ad87b78b4170848b20496ca39bf232ee898f5b1fcb19
|
data/lib/otoroshi.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Otoroshi
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
# Manages errors raised when value type is not as expected
|
7
|
+
class WrongTypeError < Error
|
8
|
+
# Initialize an error
|
9
|
+
#
|
10
|
+
# @param property [Symbol] name of the property
|
11
|
+
# @param type [Class] class to match
|
12
|
+
# @param collection [true, false] define if it is a collection
|
13
|
+
def initialize(property, type, collection: false)
|
14
|
+
expected_type = type.is_a?(Array) ? type.first || Object : type
|
15
|
+
msg =
|
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)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Manages errors raised when value is not accepted (not included in the "one_of")
|
37
|
+
class NotAcceptedError < Error
|
38
|
+
# Initialize an error
|
39
|
+
#
|
40
|
+
# @param property [Symbol] name of the property
|
41
|
+
# @param accepted_values [Array] accepted values
|
42
|
+
# @param collection [true, false] define if it is an collection
|
43
|
+
def initialize(property, accepted_values, collection: false)
|
44
|
+
# reintegrate the colon for symbols which is lost during interpolation
|
45
|
+
to_s = ->(v) { v.is_a?(Symbol) ? ":#{v}" : v }
|
46
|
+
accepted_values_list = accepted_values.map { |v| to_s.call(v) }.join(', ')
|
47
|
+
msg =
|
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)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Manages errors raised when value does not pass the assertion
|
58
|
+
class AssertionError < Error
|
59
|
+
# Initialize an error
|
60
|
+
#
|
61
|
+
# @param property [Symbol] name of the property
|
62
|
+
# @param collection [true, false] define if it is an collection
|
63
|
+
def initialize(property, collection: false)
|
64
|
+
msg =
|
65
|
+
if collection
|
66
|
+
":#{property} contains elements that do not respect the assertion"
|
67
|
+
else
|
68
|
+
":#{property} does not respect the assertion"
|
69
|
+
end
|
70
|
+
super(msg)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Otoroshi
|
4
|
+
# Drawing of #initialize method
|
5
|
+
#
|
6
|
+
class Initializer
|
7
|
+
class << self
|
8
|
+
# Draw a stringified initialize method
|
9
|
+
#
|
10
|
+
# @param properties [Hash] a description of the class properties
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# <<-RUBY
|
16
|
+
# def initialize(foo:, bar: 0)
|
17
|
+
# self.foo = foo
|
18
|
+
# self.bar = bar
|
19
|
+
# end
|
20
|
+
# RUBY
|
21
|
+
def draw(properties)
|
22
|
+
new(properties).draw
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Initialize an instance
|
27
|
+
#
|
28
|
+
# @param properties [Hash] a description of the class properties
|
29
|
+
def initialize(properties = {})
|
30
|
+
@properties = properties
|
31
|
+
end
|
32
|
+
|
33
|
+
# Draws a stringified initialize method
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# <<-RUBY
|
39
|
+
# def initialize(foo:, bar: 0)
|
40
|
+
# self.foo = foo
|
41
|
+
# self.bar = bar
|
42
|
+
# end
|
43
|
+
# RUBY
|
44
|
+
def draw
|
45
|
+
<<-RUBY
|
46
|
+
def initialize(#{initialize_parameters})
|
47
|
+
#{initialize_assignments}
|
48
|
+
#{initialize_push_singletons}
|
49
|
+
end
|
50
|
+
RUBY
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :properties
|
56
|
+
|
57
|
+
# Generates initialize method parameters
|
58
|
+
#
|
59
|
+
# @return [String]
|
60
|
+
#
|
61
|
+
# @example Given properties { foo: { allow_nil: false, default: nil }, { allow_nil: true, default: 0 } }
|
62
|
+
# redefine_initialize #=> "foo:, bar: 0"
|
63
|
+
def initialize_parameters
|
64
|
+
parameters =
|
65
|
+
properties.map do |key, options|
|
66
|
+
"#{key}:#{default_parameter_for(options)}"
|
67
|
+
end
|
68
|
+
parameters.join(', ')
|
69
|
+
end
|
70
|
+
|
71
|
+
# Fixes the default value of a parameter depending on options
|
72
|
+
#
|
73
|
+
# @return [String]
|
74
|
+
#
|
75
|
+
# @example when nil is allowed and default is set
|
76
|
+
# default_parameter_for #=> " 0"
|
77
|
+
# @example when nil is allowed and default is not set
|
78
|
+
# default_parameter_for #=> " nil"
|
79
|
+
# @example when nil is not allowed
|
80
|
+
# default_parameter_for #=> ""
|
81
|
+
def default_parameter_for(options)
|
82
|
+
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
|
87
|
+
allow_nil ? ' nil' : ''
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Generates initialize method assignments
|
92
|
+
#
|
93
|
+
# @return [String]
|
94
|
+
#
|
95
|
+
# @example Given properties { foo: { allow_nil: false, default: nil }, { allow_nil: true, default: 0 } }
|
96
|
+
# initialize_body #=> "self.foo = foo\nself.bar = bar"
|
97
|
+
def initialize_assignments
|
98
|
+
assignments =
|
99
|
+
properties.keys.map do |name|
|
100
|
+
"self.#{name} = #{name}"
|
101
|
+
end
|
102
|
+
assignments.join("\n")
|
103
|
+
end
|
104
|
+
|
105
|
+
# Generates push singleton for each array property
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
def initialize_push_singletons
|
109
|
+
collections =
|
110
|
+
properties.select do |_, options|
|
111
|
+
options[:type].is_a?(Array) || options[:type] == Array
|
112
|
+
end
|
113
|
+
singletons =
|
114
|
+
collections.keys.map do |name|
|
115
|
+
initialize_push_singleton(name)
|
116
|
+
end
|
117
|
+
singletons.join("\n")
|
118
|
+
end
|
119
|
+
|
120
|
+
# Generates singleton on collection instance variable to overide <<
|
121
|
+
# so value is validated before being added to the collection
|
122
|
+
#
|
123
|
+
# @return [String]
|
124
|
+
def initialize_push_singleton(name)
|
125
|
+
<<-RUBY
|
126
|
+
bind = self
|
127
|
+
@#{name}.singleton_class.send(:define_method, :<<) do |v|
|
128
|
+
bind.send(:"validate_#{name}_type!", [v])
|
129
|
+
bind.send(:"validate_#{name}_inclusion!", [v])
|
130
|
+
bind.send(:"validate_#{name}_assertion!", [v])
|
131
|
+
|
132
|
+
push(v)
|
133
|
+
end
|
134
|
+
RUBY
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/otoroshi/sanctuary.rb
CHANGED
@@ -1,232 +1,259 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'initializer'
|
4
|
+
|
3
5
|
module Otoroshi
|
4
|
-
#
|
6
|
+
# This module is designed to be included in a class. This will provide
|
7
|
+
# the "property" ({Sanctuary::ClassMethods.property}) method for defining class properties.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class Importer
|
11
|
+
# include Otoroshi::Sanctuary
|
12
|
+
#
|
13
|
+
# property :whatever
|
14
|
+
# property :number, Integer
|
15
|
+
# property :numbers, [Integer]
|
16
|
+
# property :positive_number, Integer, verify: ->(v) { v >= 0 }
|
17
|
+
# property :number_or_nil, Integer, allow_nil: true
|
18
|
+
# property :number_with_default, Integer, default: 42
|
19
|
+
# property :number_in_collection, Integer, one_of: [1, 2, 3, 5, 8, 13, 21, 34]
|
20
|
+
# end
|
5
21
|
module Sanctuary
|
6
|
-
# Initialize an instance
|
7
|
-
# This method will be redefined each time a property is added to the class
|
8
|
-
def initialize; end
|
9
|
-
|
10
22
|
class << self
|
11
|
-
# Extend
|
23
|
+
# Extend ClassMethods for the base class
|
12
24
|
def included(base)
|
13
25
|
base.extend ClassMethods
|
14
26
|
end
|
15
27
|
end
|
16
28
|
|
17
|
-
#
|
29
|
+
# Class methods extended for the base class
|
18
30
|
module ClassMethods
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
# Adds a new "property" to the class
|
32
|
+
#
|
33
|
+
# @param name [Symbol] the property name
|
34
|
+
# @param type [Class, Array<Class>] the expected value or values type
|
35
|
+
# @param one_of [Array] the accepted values
|
36
|
+
# @param assert [Proc] a lambda processing the value and returning true or false
|
37
|
+
# @param allow_nil [true, false] allow nil as a value
|
38
|
+
# @param default [Object] default value if not set on initialization
|
39
|
+
#
|
40
|
+
# @return [void]
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# property name, type: String, assert: ->(v) { v.length > 3 }, allow_nil: true
|
44
|
+
# @example
|
45
|
+
# property scores, type: [Integer], assert: ->(v) { v >= 0 }, default: []
|
46
|
+
def property(name, type = Object, one_of: nil, assert: ->(_) { true }, allow_nil: false, default: nil)
|
47
|
+
add_to_properties(name, type, allow_nil, default)
|
48
|
+
collection = type == Array || type.is_a?(Array)
|
49
|
+
define_validate_type!(name, type, collection, allow_nil)
|
50
|
+
define_validate_inclusion!(name, collection, one_of, allow_nil)
|
51
|
+
define_validate_assertion!(name, collection, assert, allow_nil)
|
31
52
|
define_getter(name)
|
32
53
|
define_setter(name)
|
33
|
-
|
54
|
+
class_eval Initializer.draw(properties), __FILE__, __LINE__ + 1
|
34
55
|
end
|
35
56
|
|
36
|
-
#
|
37
|
-
#
|
57
|
+
# Returns the class properties
|
58
|
+
#
|
59
|
+
# @return [Hash]
|
38
60
|
#
|
61
|
+
# @note this method will be updated by {add_to_properties}
|
39
62
|
def properties
|
40
63
|
{}
|
41
64
|
end
|
42
65
|
|
43
66
|
private
|
44
67
|
|
45
|
-
#
|
68
|
+
# Updates {properties} to add new property to the returned ones
|
46
69
|
#
|
47
|
-
|
70
|
+
# @return [void]
|
71
|
+
def add_to_properties(name, type, allow_nil, default)
|
48
72
|
current_state = properties
|
49
|
-
current_state[name] = {
|
73
|
+
current_state[name] = {
|
74
|
+
type: type,
|
75
|
+
allow_nil: allow_nil,
|
76
|
+
default: default
|
77
|
+
}
|
50
78
|
define_singleton_method(:properties) { current_state }
|
51
79
|
end
|
52
80
|
|
53
|
-
#
|
54
|
-
#
|
55
|
-
# / Examples
|
56
|
-
#
|
57
|
-
# ::define_validate_type!("score", Integer, false) --> will define:
|
81
|
+
# Defines a private method that raises an error if type is not respected
|
58
82
|
#
|
59
|
-
#
|
60
|
-
# return if allow_nil && value.nil?
|
61
|
-
# return if value.is_a?(Integer)
|
83
|
+
# @return [void]
|
62
84
|
#
|
63
|
-
#
|
64
|
-
#
|
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
|
+
# def validate_score_type!(value)
|
90
|
+
# return if Integer.nil? || false && value.nil?
|
91
|
+
# return if value.is_a? Integer
|
65
92
|
#
|
66
|
-
|
93
|
+
# raise ArgumentError, ":score does not match required type"
|
94
|
+
# end
|
95
|
+
def define_validate_type!(name, type, collection, allow_nil)
|
67
96
|
lambda = type_validation(type)
|
97
|
+
check_collection = ->(v) { v.is_a?(Array) || raise(Otoroshi::NotAnArray, name) }
|
68
98
|
define_method :"validate_#{name}_type!" do |value|
|
69
|
-
return if
|
99
|
+
return if allow_nil && value.nil?
|
100
|
+
|
101
|
+
collection && check_collection.call(value)
|
70
102
|
return if lambda.call(value)
|
71
103
|
|
72
|
-
raise
|
104
|
+
raise Otoroshi::WrongTypeError.new(name, type, collection: collection)
|
73
105
|
end
|
74
106
|
private :"validate_#{name}_type!"
|
75
107
|
end
|
76
108
|
|
77
|
-
#
|
78
|
-
# ----------------------------------------------------------------
|
109
|
+
# Defines a lambda to be called to validate that value matches the type
|
79
110
|
#
|
80
|
-
#
|
111
|
+
# @return [Proc] the lambda to use in order to test that the value matches the type
|
81
112
|
#
|
82
|
-
#
|
83
|
-
# ->(v) { v.is_a? Integer }
|
84
|
-
#
|
85
|
-
#
|
86
|
-
# ->(v) { [String, Symbol].any? { |t| v.is_a? t } }
|
113
|
+
# @example
|
114
|
+
# type_validation(Integer) #=> ->(v) { v.is_a? Integer }
|
115
|
+
# @example
|
116
|
+
# type_validation([String, Symbol]) #=> ->(v) { [String, Symbol].any? { |t| v.is_a? t } }
|
87
117
|
#
|
118
|
+
# @note params are used for binding in define_method scope
|
88
119
|
def type_validation(type)
|
89
|
-
if type
|
90
|
-
|
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) } }
|
91
130
|
else
|
131
|
+
# check the value matches the type
|
92
132
|
->(v) { v.is_a? type }
|
93
133
|
end
|
94
134
|
end
|
95
135
|
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
136
|
+
# Defines a private method that raises an error if value is not included in the accepted ones
|
137
|
+
#
|
138
|
+
# @return [void]
|
139
|
+
#
|
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
|
+
# def validate_side_type!(value)
|
146
|
+
# return if false && value.nil?
|
147
|
+
# return if [:left, :right].include? value
|
148
|
+
#
|
149
|
+
# raise ArgumentError, ":side is not included in accepted values"
|
150
|
+
# end
|
151
|
+
def define_validate_inclusion!(name, collection, one_of, allow_nil)
|
152
|
+
validator = collection ? each_inside?(name, one_of) : inside?(name, one_of)
|
153
|
+
if one_of
|
154
|
+
define_method(:"validate_#{name}_inclusion!") do |value|
|
155
|
+
allow_nil && value.nil? || validator.call(value)
|
156
|
+
end
|
157
|
+
else
|
158
|
+
define_method(:"validate_#{name}_inclusion!") { |_| }
|
116
159
|
end
|
117
|
-
private :"validate_#{name}
|
160
|
+
private :"validate_#{name}_inclusion!"
|
118
161
|
end
|
119
162
|
|
120
|
-
#
|
121
|
-
# ---------------------------------------
|
163
|
+
# Defines a lambda to be called to validate that value is included in accepted ones
|
122
164
|
#
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
# @score
|
129
|
-
# end
|
130
|
-
#
|
131
|
-
def define_getter(name)
|
132
|
-
define_method(name) { instance_variable_get("@#{name}") }
|
165
|
+
# @return [Proc] the lambda to use in order to test that value is included in accepted ones
|
166
|
+
def inside?(name, one_of)
|
167
|
+
lambda do |v|
|
168
|
+
one_of.include?(v) || raise(Otoroshi::NotAcceptedError.new(name, one_of))
|
169
|
+
end
|
133
170
|
end
|
134
171
|
|
135
|
-
#
|
136
|
-
# ---------------------------------------
|
137
|
-
#
|
138
|
-
# / Examples
|
139
|
-
#
|
140
|
-
# ::define_setter("score") --> will define:
|
172
|
+
# Defines a lambda to be called to validate that each value is included in accepted ones
|
141
173
|
#
|
142
|
-
#
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# end
|
147
|
-
#
|
148
|
-
def define_setter(name)
|
149
|
-
define_method :"#{name}=" do |value|
|
150
|
-
__send__(:"validate_#{name}_type!", value)
|
151
|
-
__send__(:"validate_#{name}_lambda!", value)
|
152
|
-
instance_variable_set("@#{name}", value)
|
174
|
+
# @return [Proc] the lambda to use in order to test that each value is included in accepted ones
|
175
|
+
def each_inside?(name, one_of)
|
176
|
+
lambda do |v|
|
177
|
+
v.all? { |e| one_of.include? e } || raise(Otoroshi::NotAcceptedError.new(name, one_of, collection: true))
|
153
178
|
end
|
154
179
|
end
|
155
180
|
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
177
|
-
RUBY
|
181
|
+
# Defines a private method that raises an error if assert lambda returns false
|
182
|
+
#
|
183
|
+
# @return [void]
|
184
|
+
#
|
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
|
+
# def validate_score_assertion!(value)
|
190
|
+
# return if false && value.nil?
|
191
|
+
# return if value >= 0
|
192
|
+
#
|
193
|
+
# raise ArgumentError, ":score does not match validation"
|
194
|
+
# end
|
195
|
+
def define_validate_assertion!(name, collection, assert, allow_nil)
|
196
|
+
validator = collection ? each_assert?(name, assert) : assert?(name, assert)
|
197
|
+
define_method :"validate_#{name}_assertion!" do |value|
|
198
|
+
allow_nil && value.nil? || validator.call(value)
|
199
|
+
end
|
200
|
+
private :"validate_#{name}_assertion!"
|
178
201
|
end
|
179
202
|
|
180
|
-
#
|
181
|
-
# -----------------------------------
|
182
|
-
#
|
183
|
-
# / Examples
|
184
|
-
#
|
185
|
-
# Given the properties:
|
186
|
-
# foo: { allow_nil: false, default: nil }
|
187
|
-
# bar: { allow_nil: true, default: 0 }
|
188
|
-
#
|
189
|
-
# ::initialize_parameters --> will return:
|
190
|
-
# "foo:, bar: 0"
|
203
|
+
# Defines a lambda to be called to validate that value respects the specific
|
191
204
|
#
|
192
|
-
|
193
|
-
|
205
|
+
# @return [Proc] the lambda to use in order to test that value respects the specific
|
206
|
+
def assert?(name, assert)
|
207
|
+
lambda do |value|
|
208
|
+
instance_exec(value, &assert) || raise(Otoroshi::AssertionError, name)
|
209
|
+
end
|
194
210
|
end
|
195
211
|
|
196
|
-
#
|
197
|
-
# ------------------------------------------------------------
|
198
|
-
#
|
199
|
-
# / Examples
|
200
|
-
#
|
201
|
-
# default_parameter_for(allow_nil: true, default: 0) --> will return
|
202
|
-
# ' 0'
|
212
|
+
# Defines a lambda to be called to validate that value respects the specific
|
203
213
|
#
|
204
|
-
#
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
def default_parameter_for(options)
|
211
|
-
return " #{options[:default]}" if options[:default]
|
212
|
-
|
213
|
-
options[:allow_nil] ? ' nil' : ''
|
214
|
+
# @return [Proc] the lambda to use in order to test that each value respects the specific
|
215
|
+
def each_assert?(name, assert)
|
216
|
+
lambda do |value|
|
217
|
+
value.all? { |e| instance_exec(e, &assert) } ||
|
218
|
+
raise(Otoroshi::AssertionError.new(name, collection: true))
|
219
|
+
end
|
214
220
|
end
|
215
221
|
|
216
|
-
#
|
217
|
-
# -----------------------------
|
222
|
+
# Defines a getter method for the property
|
218
223
|
#
|
219
|
-
#
|
224
|
+
# @return [void]
|
220
225
|
#
|
221
|
-
#
|
222
|
-
# :
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
def
|
229
|
-
|
226
|
+
# @example
|
227
|
+
# define_getter(:score) #=> def score ...
|
228
|
+
# @example Generated instance method
|
229
|
+
# # given name: :score
|
230
|
+
# def score
|
231
|
+
# instance_variable_get(@score)
|
232
|
+
# end
|
233
|
+
def define_getter(name)
|
234
|
+
define_method(name) { instance_variable_get("@#{name}") }
|
235
|
+
end
|
236
|
+
|
237
|
+
# Defines a setter method for the property
|
238
|
+
#
|
239
|
+
# @return [void]
|
240
|
+
#
|
241
|
+
# @example
|
242
|
+
# define_setter(:score) #=> def score=(value) ...
|
243
|
+
# @example Generated instance method
|
244
|
+
# # given name: :score
|
245
|
+
# def score=(value)
|
246
|
+
# validate_score_type!(value)
|
247
|
+
# validate_score!(value)
|
248
|
+
# instance_variable_set(@score, value)
|
249
|
+
# end
|
250
|
+
def define_setter(name)
|
251
|
+
define_method :"#{name}=" do |value|
|
252
|
+
__send__(:"validate_#{name}_type!", value)
|
253
|
+
__send__(:"validate_#{name}_inclusion!", value)
|
254
|
+
__send__(:"validate_#{name}_assertion!", value)
|
255
|
+
instance_variable_set("@#{name}", value)
|
256
|
+
end
|
230
257
|
end
|
231
258
|
end
|
232
259
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: otoroshi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edouard Piron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-10-
|
11
|
+
date: 2020-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Help defining class properties
|
14
14
|
email: ed.piron@gmail.com
|
@@ -16,6 +16,9 @@ executables: []
|
|
16
16
|
extensions: []
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
|
+
- lib/otoroshi.rb
|
20
|
+
- lib/otoroshi/exceptions.rb
|
21
|
+
- lib/otoroshi/initializer.rb
|
19
22
|
- lib/otoroshi/sanctuary.rb
|
20
23
|
homepage: https://rubygems.org/gems/otoroshi
|
21
24
|
licenses:
|