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