otoroshi 0.0.2 → 0.0.3

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.
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: []