otoroshi 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/otoroshi/sanctuary.rb +133 -65
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 125c31a56b83045874e5c91780c2541b93c73a567914917c2b8d54c38650c32d
4
- data.tar.gz: 45869708d77341f0a45cf3fed38f7719cdd50dac6e13cb7dc528fe36ac2b3f10
3
+ metadata.gz: cec895aa30d2fb89c0b824b38c2b0b710558419aa7ef1308769b8550969924ba
4
+ data.tar.gz: a8f06adce33632af173d95282440685ab009c6095f6db889e21b25ffd4cccb40
5
5
  SHA512:
6
- metadata.gz: 435e9e8988c073ac9c3d8a661c0bdc0030e17118ffb39ca15674b86f6a2ccf9a20d0308a4a126a9c74b0b54aaaee27110e9d6a66d86b99b3f6727f3068484563
7
- data.tar.gz: d32b924aa3c1446481a2ada3390783881ef1b66a52db41f4e4beb7e72a596e5a854606276443e6f59bad5527fd69c9c3759cb94a84e2d88e1eee9ab1bb6910ac
6
+ metadata.gz: 581a9bb26d5c1f861fa5f3c0e60d554c9a4f0e2f47c17df3856d957202ab1909ec74da411b2f0878c7ab0f0e59e904c1220b77e71f67dc1543a5959da0aa3f77
7
+ data.tar.gz: 7811ee410f737e3f53d133eee22d62d0ed1e6b140d45801cad33aff475ced6a2e6b1e91acd92b4047f4c38c12b53ce64256dd935a3571e49758fa41f760d2e75
@@ -1,53 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Otoroshi
4
- # help setting and validating instance arguments
5
- class Sanctuary
4
+ # Help setting and validating instance arguments
5
+ 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
+
6
10
  class << self
7
- # Add a new property to the class (called by inherited class)
8
- # Example: property name, type: String, validate: ->(v) { v.length > 3 }, allow_nil: true
11
+ # Extend class method to the included class
12
+ def included(base)
13
+ base.extend ClassMethods
14
+ end
15
+ end
16
+
17
+ # Define class methods
18
+ module ClassMethods
19
+ # Add a new property to the class
20
+ # -------------------------------
21
+ #
22
+ # / Examples
23
+ #
24
+ # property name, type: String, validate: ->(v) { v.length > 3 }, allow_nil: true
25
+ # property score, type: Integer, validate: ->(v) { v >= 0 }, default: 0
26
+ #
9
27
  def property(name, type = Object, validate: ->(_) { true }, allow_nil: false, default: nil)
10
- define_default(name, default)
28
+ add_to_properties(name, allow_nil, default)
11
29
  define_validate_type!(name, type, allow_nil)
12
- define_validate!(name, validate, allow_nil)
30
+ define_validate_lambda!(name, validate, allow_nil)
13
31
  define_getter(name)
14
32
  define_setter(name)
15
- add_to_properties(name)
33
+ redefine_initialize
16
34
  end
17
35
 
18
36
  # Return the (inherited) class properties
19
- # (this method will be updated by ::add_to_properties(name))
37
+ # (this method will be updated by ::add_to_properties)
38
+ #
20
39
  def properties
21
- []
40
+ {}
22
41
  end
23
42
 
24
43
  private
25
44
 
26
45
  # Update the ::properties method to add new property to the current list
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
41
46
  #
42
- def define_default(name, default)
43
- define_method(:"default_#{name}") { default }
44
- private :"default_#{name}"
47
+ def add_to_properties(name, allow_nil, default)
48
+ current_state = properties
49
+ current_state[name] = { allow_nil: allow_nil, default: default }
50
+ define_singleton_method(:properties) { current_state }
45
51
  end
46
52
 
47
53
  # Define a private method that raises an error if type is not respected
48
54
  #
49
- # ::define_validate_type!("score", Integer, false)
50
- # ----------------------------------------------
55
+ # / Examples
56
+ #
57
+ # ::define_validate_type!("score", Integer, false) --> will define:
58
+ #
51
59
  # def validate_score_type!(value)
52
60
  # return if allow_nil && value.nil?
53
61
  # return if value.is_a?(Integer)
@@ -67,11 +75,16 @@ module Otoroshi
67
75
  end
68
76
 
69
77
  # Define a lambda to be call to validate that value match the type
78
+ # ----------------------------------------------------------------
79
+ #
80
+ # / Examples
70
81
  #
71
- # ::type_validation(Integer)
72
- # ----------------------------------------------
82
+ # ::type_validation(Integer) --> will return:
73
83
  # ->(v) { v.is_a? Integer }
74
84
  #
85
+ # :type_validation([String, Symbol]) --> will return:
86
+ # ->(v) { [String, Symbol].any? { |t| v.is_a? t } }
87
+ #
75
88
  def type_validation(type)
76
89
  if type.is_a? Array
77
90
  ->(v) { type.any? { |t| v.is_a? t } }
@@ -81,30 +94,36 @@ module Otoroshi
81
94
  end
82
95
 
83
96
  # Define a private method that raises an error if validate block returns false
97
+ # ----------------------------------------------------------------------------
98
+ #
99
+ # / Examples
100
+ #
101
+ # ::define_validate_lambda!("score", ->(v) { v >= 0 }, false) --> will define:
84
102
  #
85
- # ::define_validate!("score", ->(v) { v >= 0 }, false)
86
- # --------------------------------------------------
87
- # def validate_score!(value)
103
+ # def validate_score_lambda!(value)
88
104
  # return if false && value.nil?
89
105
  # return if value >= 0
90
106
  #
91
107
  # raise ArgumentError, ":score does not match validation"
92
108
  # end
93
109
  #
94
- def define_validate!(name, validate, allow_nil)
95
- define_method :"validate_#{name}!" do |value|
110
+ def define_validate_lambda!(name, validate, allow_nil)
111
+ define_method :"validate_#{name}_lambda!" do |value|
96
112
  return if allow_nil && value.nil?
97
113
  return if instance_exec(value, &validate)
98
114
 
99
115
  raise ArgumentError, ":#{name} does not match validation"
100
116
  end
101
- private :"validate_#{name}!"
117
+ private :"validate_#{name}_lambda!"
102
118
  end
103
119
 
104
120
  # Define a getter method for the property
121
+ # ---------------------------------------
122
+ #
123
+ # / Examples
124
+ #
125
+ # ::define_getter("score") --> will define:
105
126
  #
106
- # ::define_getter("score")
107
- # ----------------------
108
127
  # def score
109
128
  # @score
110
129
  # end
@@ -114,9 +133,12 @@ module Otoroshi
114
133
  end
115
134
 
116
135
  # Define a setter method for the property
136
+ # ---------------------------------------
137
+ #
138
+ # / Examples
139
+ #
140
+ # ::define_setter("score") --> will define:
117
141
  #
118
- # ::define_setter("score")
119
- # ----------------------
120
142
  # def score=(value)
121
143
  # validate_score_type!(value)
122
144
  # validate_score!(value)
@@ -126,39 +148,85 @@ module Otoroshi
126
148
  def define_setter(name)
127
149
  define_method :"#{name}=" do |value|
128
150
  __send__(:"validate_#{name}_type!", value)
129
- __send__(:"validate_#{name}!", value)
151
+ __send__(:"validate_#{name}_lambda!", value)
130
152
  instance_variable_set("@#{name}", value)
131
153
  end
132
154
  end
133
- end
134
155
 
135
- # Initialize an instance and validate provided args
136
- def initialize(args = {}) # rubocop:disable Style/OptionHash
137
- validate_keys!(args.keys)
138
- assign_values(args)
139
- end
156
+ # Redefine the initialize method
157
+ # ------------------------------
158
+ #
159
+ # / Examples
160
+ #
161
+ # Given the properties:
162
+ # foo: { allow_nil: false, default: nil }
163
+ # bar: { allow_nil: true, default: 0 }
164
+ #
165
+ # ::define_initialize --> will define:
166
+ #
167
+ # def initialize(foo:, bar: 0)
168
+ # self.foo = foo
169
+ # self.bar = bar
170
+ # end
171
+ #
172
+ def redefine_initialize
173
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
174
+ def initialize(#{initialize_parameters})
175
+ #{initialize_body}
176
+ end
177
+ RUBY
178
+ end
140
179
 
141
- private
180
+ # Define initialize method parameters
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"
191
+ #
192
+ def initialize_parameters
193
+ properties.map { |key, options| "#{key}:#{default_parameter_for(options)}" }.join(', ')
194
+ end
142
195
 
143
- # validate that provided keys match class properties
144
- def validate_keys!(keys)
145
- errors = keys.reject { |key| self.class.properties.include? key }
146
- return if errors.empty?
196
+ # Define the default value of a parameter depending on options
197
+ # ------------------------------------------------------------
198
+ #
199
+ # / Examples
200
+ #
201
+ # default_parameter_for(allow_nil: true, default: 0) --> will return
202
+ # ' 0'
203
+ #
204
+ # default_parameter_for(allow_nil: true, default: nil) --> will return
205
+ # ' nil'
206
+ #
207
+ # default_parameter_for(allow_nil: false, default: nil) --> will return
208
+ # ''
209
+ #
210
+ def default_parameter_for(options)
211
+ return " #{options[:default]}" if options[:default]
147
212
 
148
- message =
149
- if errors.one?
150
- ":#{errors[0]} is not a valid property"
151
- else
152
- ":#{errors.join(', :')} are not valid properties"
153
- end
154
- raise ArgumentError, message
155
- end
213
+ options[:allow_nil] ? ' nil' : ''
214
+ end
156
215
 
157
- # assign value to each property
158
- def assign_values(args)
159
- self.class.properties.each do |property|
160
- value = args.key?(property) ? args[property] : __send__(:"default_#{property}")
161
- public_send(:"#{property}=", value)
216
+ # Define initialize method body
217
+ # -----------------------------
218
+ #
219
+ # / Examples
220
+ #
221
+ # Given the properties:
222
+ # :foo, :bar
223
+ #
224
+ # ::initialize_body --> will return:
225
+ # "self.foo = foo
226
+ # self.bar = bar"
227
+ #
228
+ def initialize_body
229
+ properties.keys.map { |key| "self.#{key} = #{key}" }.join("\n")
162
230
  end
163
231
  end
164
232
  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.2
4
+ version: 0.0.3
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 setting and validating instance arguments
13
+ description: Help defining class properties
14
14
  email: ed.piron@gmail.com
15
15
  executables: []
16
16
  extensions: []