otoroshi 0.0.1 → 0.0.6
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/sanctuary.rb +175 -97
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e31c6e00090297fb9709600d1580a24a4729ee1a9af094015ea7c197fde884d3
|
4
|
+
data.tar.gz: 033526ab6473e809a19c812104cf05cadba29485d617161c1799f6664777f9fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5e9595b7c246dde6897fc4f314cdf0c9ef00576dd042cc9c4e34c60de249d4d346ebc2f661f1190708a26211cacbdd1a9f457a9e5802e57049b5f5d831dc9d1
|
7
|
+
data.tar.gz: 42aace4283c39b3d956022e643635d73a9b3a5feb74070f0dd441d8ef165b5d9c76475a7bd274b94e4da8f85aa0ecb08868116842c6af98b1cdf4112a93bbe77
|
data/lib/otoroshi/sanctuary.rb
CHANGED
@@ -1,77 +1,109 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Otoroshi
|
4
|
-
#
|
5
|
-
class
|
4
|
+
# This module is designed to be included in a class. This will provide
|
5
|
+
# the "property" ({Sanctuary::ClassMethods.property}) method for defining class properties.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class Importer
|
9
|
+
# include Otoroshi::Sanctuary
|
10
|
+
#
|
11
|
+
# property :file_path, String, validate: ->(v) { v.match? /.+\.csv/ }
|
12
|
+
# property :headers, [TrueClass, FalseClass], default: false
|
13
|
+
# property :col_sep, String, validate: ->(v) { v.in? [',', ';', '\s', '\t', '|'] }, default: ','
|
14
|
+
# property :converters, Symbol, validate: ->(v) { v.in? %i[integer float date] }, allow_nil: true
|
15
|
+
# end
|
16
|
+
module Sanctuary
|
6
17
|
class << self
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
18
|
+
# Extend ClassMethods for the base class
|
19
|
+
def included(base)
|
20
|
+
base.extend ClassMethods
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Class methods extended for the base class
|
25
|
+
module ClassMethods
|
26
|
+
# Adds a new "property" to the class
|
27
|
+
#
|
28
|
+
# @param name [Symbol] the property name
|
29
|
+
# @param type [Class] the expected value type
|
30
|
+
# @param validate [Proc] a lambda processing the value and returning true or false
|
31
|
+
# @param allow_nil [true, false] allow nil as a value
|
32
|
+
# @param default [Object] default value if not set on initialization
|
33
|
+
#
|
34
|
+
# @return [void]
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# property name, type: String, validate: ->(v) { v.length > 3 }, allow_nil: true
|
38
|
+
# @example
|
39
|
+
# property score, type: Integer, validate: ->(v) { v >= 0 }, default: 0
|
40
|
+
def property(name, type = Object, validate: ->(_) { true }, allow_nil: false, default: nil)
|
41
|
+
add_to_properties(name, allow_nil, default)
|
42
|
+
define_validate_type!(name, type, allow_nil)
|
43
|
+
define_validate_lambda!(name, validate, allow_nil)
|
13
44
|
define_getter(name)
|
14
45
|
define_setter(name)
|
15
|
-
|
46
|
+
redefine_initialize
|
16
47
|
end
|
17
48
|
|
18
|
-
#
|
19
|
-
#
|
49
|
+
# Returns the class properties
|
50
|
+
#
|
51
|
+
# @return [Hash]
|
52
|
+
#
|
53
|
+
# @note this method will be updated by {add_to_properties}
|
20
54
|
def properties
|
21
|
-
|
55
|
+
{}
|
22
56
|
end
|
23
57
|
|
24
58
|
private
|
25
59
|
|
26
|
-
#
|
27
|
-
def add_to_properties(name)
|
28
|
-
current = properties
|
29
|
-
define_singleton_method :properties do
|
30
|
-
current << name
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Define a private method that returns the default value
|
35
|
-
#
|
36
|
-
# ::define_default("score", 0)
|
37
|
-
# --------------------------
|
38
|
-
# def default_score
|
39
|
-
# 0
|
40
|
-
# end
|
60
|
+
# Updates {properties} to add new property to the returned ones
|
41
61
|
#
|
42
|
-
|
43
|
-
|
44
|
-
|
62
|
+
# @return [void]
|
63
|
+
def add_to_properties(name, allow_nil, default)
|
64
|
+
current_state = properties
|
65
|
+
current_state[name] = { allow_nil: allow_nil, default: default }
|
66
|
+
define_singleton_method(:properties) { current_state }
|
45
67
|
end
|
46
68
|
|
47
|
-
#
|
69
|
+
# Defines a private method that raises an error if type is not respected
|
48
70
|
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# return if optional && value.nil?
|
53
|
-
# return if value.is_a?(Integer)
|
71
|
+
# @param name [Symbol] the property name
|
72
|
+
# @param type [Class] the type to test against
|
73
|
+
# @param allow_nil [true, false] allow nil as a value
|
54
74
|
#
|
55
|
-
#
|
56
|
-
# end
|
75
|
+
# @return [void]
|
57
76
|
#
|
58
|
-
|
77
|
+
# @example
|
78
|
+
# define_validate_type!(score, Integer, false) => def validate_score_type!(value) ...
|
79
|
+
# @example Generated method
|
80
|
+
# def validate_score_type!(value)
|
81
|
+
# return if Integer.nil? || false && value.nil?
|
82
|
+
# return if value.is_a? Integer
|
83
|
+
#
|
84
|
+
# raise ArgumentError, ":score does not match required type"
|
85
|
+
# end
|
86
|
+
def define_validate_type!(name, type, allow_nil)
|
59
87
|
lambda = type_validation(type)
|
60
88
|
define_method :"validate_#{name}_type!" do |value|
|
61
|
-
return if type.nil? ||
|
89
|
+
return if type.nil? || allow_nil && value.nil?
|
62
90
|
return if lambda.call(value)
|
63
91
|
|
64
|
-
raise ArgumentError, ":#{name} does not match type
|
92
|
+
raise ArgumentError, ":#{name} does not match required type"
|
65
93
|
end
|
66
94
|
private :"validate_#{name}_type!"
|
67
95
|
end
|
68
96
|
|
69
|
-
#
|
97
|
+
# Defines a lambda to be call to validate that value matches the type
|
98
|
+
#
|
99
|
+
# @param type [Class] the type to test against
|
70
100
|
#
|
71
|
-
#
|
72
|
-
# ----------------------------------------------
|
73
|
-
# ->(v) { v.is_a? Integer }
|
101
|
+
# @return [Proc] the lambda to use in order to test the value matches the type
|
74
102
|
#
|
103
|
+
# @example
|
104
|
+
# type_validation(Integer) #=> ->(v) { v.is_a? Integer }
|
105
|
+
# @example
|
106
|
+
# type_validation([String, Symbol]) #=> ->(v) { [String, Symbol].any? { |t| v.is_a? t } }
|
75
107
|
def type_validation(type)
|
76
108
|
if type.is_a? Array
|
77
109
|
->(v) { type.any? { |t| v.is_a? t } }
|
@@ -80,85 +112,131 @@ module Otoroshi
|
|
80
112
|
end
|
81
113
|
end
|
82
114
|
|
83
|
-
#
|
115
|
+
# Defines a private method that raises an error if validate block returns false
|
84
116
|
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# return if false && value.nil?
|
89
|
-
# return if value >= 0
|
117
|
+
# @param name [Symbol] the property name
|
118
|
+
# @param validate [Proc] a lambda processing the value and returning true or false
|
119
|
+
# @param allow_nil [true, false] allow nil as a value
|
90
120
|
#
|
91
|
-
#
|
92
|
-
# end
|
121
|
+
# @return [void]
|
93
122
|
#
|
94
|
-
|
95
|
-
|
96
|
-
|
123
|
+
# @example
|
124
|
+
# define_validate_lambda!("score", ->(v) { v >= 0 }, false) #=> def validate_score_lambda!(value) ...
|
125
|
+
# @example Generated instance method
|
126
|
+
# def validate_score_lambda!(value)
|
127
|
+
# return if false && value.nil?
|
128
|
+
# return if value >= 0
|
129
|
+
#
|
130
|
+
# raise ArgumentError, ":score does not match validation"
|
131
|
+
# end
|
132
|
+
def define_validate_lambda!(name, validate, allow_nil)
|
133
|
+
define_method :"validate_#{name}_lambda!" do |value|
|
134
|
+
return if allow_nil && value.nil?
|
97
135
|
return if instance_exec(value, &validate)
|
98
136
|
|
99
137
|
raise ArgumentError, ":#{name} does not match validation"
|
100
138
|
end
|
101
|
-
private :"validate_#{name}!"
|
139
|
+
private :"validate_#{name}_lambda!"
|
102
140
|
end
|
103
141
|
|
104
|
-
#
|
142
|
+
# Defines a getter method for the property
|
143
|
+
#
|
144
|
+
# @param name [Symbol] the property name
|
105
145
|
#
|
106
|
-
#
|
107
|
-
# ----------------------
|
108
|
-
# def score
|
109
|
-
# @score
|
110
|
-
# end
|
146
|
+
# @return [void]
|
111
147
|
#
|
148
|
+
# @example
|
149
|
+
# define_getter(:score) #=> def score ...
|
150
|
+
# @example Generated instance method
|
151
|
+
# def score
|
152
|
+
# instance_variable_get(@score)
|
153
|
+
# end
|
112
154
|
def define_getter(name)
|
113
155
|
define_method(name) { instance_variable_get("@#{name}") }
|
114
156
|
end
|
115
157
|
|
116
|
-
#
|
158
|
+
# Defines a setter method for the property
|
117
159
|
#
|
118
|
-
#
|
119
|
-
# ----------------------
|
120
|
-
# def score=(value)
|
121
|
-
# validate_score_type!(value)
|
122
|
-
# validate_score!(value)
|
123
|
-
# @score = value
|
124
|
-
# end
|
160
|
+
# @param name [Symbol] the property name
|
125
161
|
#
|
162
|
+
# @return [void]
|
163
|
+
#
|
164
|
+
# @example
|
165
|
+
# define_getter(:score) #=> def score=(value) ...
|
166
|
+
# @example Generated instance method
|
167
|
+
# def score=(value)
|
168
|
+
# validate_score_type!(value)
|
169
|
+
# validate_score!(value)
|
170
|
+
# instance_variable_set(@score, value)
|
171
|
+
# end
|
126
172
|
def define_setter(name)
|
127
173
|
define_method :"#{name}=" do |value|
|
128
174
|
__send__(:"validate_#{name}_type!", value)
|
129
|
-
__send__(:"validate_#{name}!", value)
|
175
|
+
__send__(:"validate_#{name}_lambda!", value)
|
130
176
|
instance_variable_set("@#{name}", value)
|
131
177
|
end
|
132
178
|
end
|
133
|
-
end
|
134
179
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
180
|
+
# Redefines initialize method
|
181
|
+
#
|
182
|
+
# @return [void]
|
183
|
+
#
|
184
|
+
# @note method is defined with `class_eval`
|
185
|
+
#
|
186
|
+
# @example Generated method
|
187
|
+
# def initialize(foo:, bar: 0)
|
188
|
+
# self.foo = foo
|
189
|
+
# self.bar = bar
|
190
|
+
# end
|
191
|
+
def redefine_initialize
|
192
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
193
|
+
def initialize(#{initialize_parameters})
|
194
|
+
#{initialize_body}
|
195
|
+
end
|
196
|
+
RUBY
|
197
|
+
end
|
142
198
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
199
|
+
# Defines initialize method parameters
|
200
|
+
#
|
201
|
+
# @return [String]
|
202
|
+
#
|
203
|
+
# @example Given properties { foo: { allow_nil: false, default: nil }, { allow_nil: true, default: 0 } }
|
204
|
+
# redefine_initialize #=> "foo:, bar: 0"
|
205
|
+
def initialize_parameters
|
206
|
+
parameters =
|
207
|
+
properties.map do |key, options|
|
208
|
+
allow_nil, default = options.values
|
209
|
+
"#{key}:#{default_parameter_for(allow_nil, default)}"
|
210
|
+
end
|
211
|
+
parameters.join(', ')
|
212
|
+
end
|
147
213
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
214
|
+
# Defines the default value of a parameter depending on options
|
215
|
+
#
|
216
|
+
# @param options [Hash]
|
217
|
+
#
|
218
|
+
# @return [String]
|
219
|
+
#
|
220
|
+
# @example when nil is allowed and default is set
|
221
|
+
# default_parameter_for(true, 0) #=> " 0"
|
222
|
+
# @example when nil is allowed and default is not set
|
223
|
+
# default_parameter_for(true, nil) #=> " nil"
|
224
|
+
# @example when nil is not allowed
|
225
|
+
# default_parameter_for(false, nil) #=> ""
|
226
|
+
def default_parameter_for(allow_nil, default)
|
227
|
+
return " #{default}" if default
|
228
|
+
|
229
|
+
allow_nil ? ' nil' : ''
|
230
|
+
end
|
156
231
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
232
|
+
# Defines initialize method body
|
233
|
+
#
|
234
|
+
# @return [String]
|
235
|
+
#
|
236
|
+
# @example Given properties { foo: { allow_nil: false, default: nil }, { allow_nil: true, default: 0 } }
|
237
|
+
# initialize_body #=> "self.foo = foo\nself.bar = bar"
|
238
|
+
def initialize_body
|
239
|
+
properties.keys.map { |key| "self.#{key} = #{key}" }.join("\n")
|
162
240
|
end
|
163
241
|
end
|
164
242
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edouard Piron
|
@@ -10,7 +10,7 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2020-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: Help
|
13
|
+
description: Help defining class properties
|
14
14
|
email: ed.piron@gmail.com
|
15
15
|
executables: []
|
16
16
|
extensions: []
|