sinclair 1.10.0 → 1.11.0

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/README.md +414 -324
  4. data/config/check_specs.yml +3 -4
  5. data/config/yardstick.yml +2 -0
  6. data/lib/sinclair/matchers/add_class_method.rb +0 -1
  7. data/lib/sinclair/method_builder/base.rb +17 -2
  8. data/lib/sinclair/method_builder/call_method_builder.rb +21 -21
  9. data/lib/sinclair/method_builder.rb +5 -20
  10. data/lib/sinclair/method_definition/block_definition.rb +2 -0
  11. data/lib/sinclair/method_definition/call_definition.rb +15 -18
  12. data/lib/sinclair/method_definition/string_definition.rb +2 -0
  13. data/lib/sinclair/method_definition.rb +41 -3
  14. data/lib/sinclair/method_definitions.rb +20 -22
  15. data/lib/sinclair/version.rb +1 -1
  16. data/lib/sinclair.rb +149 -62
  17. data/spec/integration/readme/sinclair/types_of_definition_spec.rb +47 -0
  18. data/spec/integration/yard/sinclair/add_class_method_spec.rb +51 -0
  19. data/spec/integration/yard/sinclair/add_method_spec.rb +60 -0
  20. data/spec/integration/yard/sinclair/eval_and_add_method_spec.rb +26 -0
  21. data/spec/integration/yard/sinclair_spec.rb +0 -83
  22. data/spec/lib/sinclair/method_builder/base_spec.rb +15 -0
  23. data/spec/lib/sinclair/method_definition/call_definition_spec.rb +14 -17
  24. data/spec/lib/sinclair/method_definition_spec.rb +67 -2
  25. data/spec/lib/sinclair/method_definitions_spec.rb +15 -16
  26. data/spec/lib/sinclair_spec.rb +6 -160
  27. data/spec/support/models/dummy_builder.rb +4 -1
  28. data/spec/support/models/dummy_class_builder.rb +3 -0
  29. data/spec/support/models/person.rb +1 -1
  30. data/spec/support/shared_examples/sinclair.rb +112 -0
  31. metadata +8 -2
@@ -1,10 +1,9 @@
1
1
  ignore:
2
2
  - lib/sinclair/comparable/class_methods.rb
3
+ - lib/sinclair/exception.rb
3
4
  - lib/sinclair/matchers/add_method_to.rb
4
5
  - lib/sinclair/matchers/add_method.rb
5
- - lib/sinclair/version.rb
6
- - lib/sinclair/method_builder/base.rb
7
- - lib/sinclair/exception.rb
8
- - lib/sinclair/matchers/method_to.rb
9
6
  - lib/sinclair/matchers/base.rb
7
+ - lib/sinclair/matchers/method_to.rb
10
8
  - lib/sinclair/matchers/change_method_on.rb
9
+ - lib/sinclair/version.rb
data/config/yardstick.yml CHANGED
@@ -16,6 +16,8 @@ rules:
16
16
  ExampleTag:
17
17
  enabled: true
18
18
  exclude:
19
+ - Sinclair#add_method
20
+ - Sinclair#add_class_method
19
21
  - Sinclair::Configurable#config
20
22
  - Sinclair::Configurable#reset_config
21
23
  - Sinclair::Configurable#configure
@@ -7,7 +7,6 @@ class Sinclair
7
7
  #
8
8
  # AddClassMethod is able to build an instance of {Sinclair::Matchers::AddClassMethodTo}
9
9
  class AddClassMethod < AddMethod
10
- # @method #to(target = nil)
11
10
  # @example Checking if a class had a class method added
12
11
  # RSpec.configure do |config|
13
12
  # config.include Sinclair::Matchers
@@ -7,6 +7,21 @@ class Sinclair
7
7
  #
8
8
  # Base class responsible for building methods
9
9
  class Base
10
+ # Instantiate the class and build the method
11
+ #
12
+ # @param klass [Class] class to receive the method
13
+ # @param definition [MethodDefinition] method defined
14
+ # @param type [Symbol] type of method to be build
15
+ # - +:instance+ instance methods
16
+ # - +:class+ class methods
17
+ #
18
+ # @see #build
19
+ #
20
+ # @return [Symbol] name of the method built
21
+ def self.build(klass, definition, type:)
22
+ new(klass, definition, type: type).build
23
+ end
24
+
10
25
  # @param klass [Class] class to receive the method
11
26
  # @param definition [MethodDefinition] method defined
12
27
  # @param type [Symbol] type of method to be build
@@ -22,9 +37,9 @@ class Sinclair
22
37
  #
23
38
  # @return [Symbol] name of the method built
24
39
  #
25
- # @raise NotImplementedYet
40
+ # @raise NotImplementedError
26
41
  def build
27
- raise 'Not implemented yet. this should be imlemented in subclasses'
42
+ raise NotImplementedError, 'Not implemented yet. this should be imlemented in subclasses'
28
43
  end
29
44
 
30
45
  private
@@ -9,41 +9,41 @@ class Sinclair
9
9
  class CallMethodBuilder < Base
10
10
  # Builds the method
11
11
  #
12
+ # The build uses +module_eval+ over a class
13
+ #
14
+ # The code is ran either on the class itself or in
15
+ # a block that allow creation of class methods
16
+ #
12
17
  # @return [NilClass]
13
18
  def build
14
- klass.module_eval(code_line, __FILE__, __LINE__ + 1)
19
+ evaluating_class.module_eval(&code_block)
15
20
  end
16
21
 
17
22
  private
18
23
 
24
+ delegate :code_block, to: :definition
25
+ # @method code_block
19
26
  # @api private
20
27
  # @private
21
28
  #
22
- # String to be evaluated when building the method
29
+ # Code block to be evaluated by the class
23
30
  #
24
- # This can be {code_string} or {class_code_string}
25
- # @return (see MethodDefinition::CallDefinition#code_string)
26
- def code_line
27
- instance? ? code_string : class_code_string
28
- end
31
+ # @return [Proc]
29
32
 
30
- delegate :code_string, :class_code_string, to: :definition
31
-
32
- # @method code_string
33
- # @private
34
- # @api private
33
+ # Returns the klass where the proc block will be evaluated
35
34
  #
36
- # Delegated from {MethodDefinition::CallDefinition}
35
+ # For instance type, the class itself is returned
37
36
  #
38
- # @see MethodDefinition::CallDefinition#code_string
39
- # @return [String]
40
-
41
- # @method class_code_string
42
- # @private
43
- # @api private
37
+ # For adding class methods, the superclass is returned
44
38
  #
45
- # @see MethodDefinition::CallDefinition#class_code_string
46
- # @return [String]
39
+ # @return [Class]
40
+ def evaluating_class
41
+ return klass if instance?
42
+
43
+ class << klass
44
+ return self
45
+ end
46
+ end
47
47
  end
48
48
  end
49
49
  end
@@ -9,7 +9,8 @@ class Sinclair
9
9
  autoload :Base, 'sinclair/method_builder/base'
10
10
  autoload :StringMethodBuilder, 'sinclair/method_builder/string_method_builder'
11
11
  autoload :BlockMethodBuilder, 'sinclair/method_builder/block_method_builder'
12
- autoload :CallMethodBuilder, 'sinclair/method_builder/call_method_builder'
12
+
13
+ autoload :CallMethodBuilder, 'sinclair/method_builder/call_method_builder'
13
14
 
14
15
  CLASS_METHOD = :class
15
16
  INSTANCE_METHOD = :instance
@@ -24,11 +25,13 @@ class Sinclair
24
25
  # @param definitions [MethodDefinitions] all methods
25
26
  # definitions to be built
26
27
  # @param type [Symbol] type of method to be built
28
+ # - {CLASS_METHOD} : A class method will be built
29
+ # - {INSTANCE_METHOD} : An instance method will be built
27
30
  #
28
31
  # @return [MethodDefinitions]
29
32
  def build_methods(definitions, type)
30
33
  definitions.each do |definition|
31
- build_from_definition(definition, type)
34
+ definition.build(klass, type)
32
35
  end
33
36
  end
34
37
 
@@ -42,23 +45,5 @@ class Sinclair
42
45
  # class to receive the method
43
46
  #
44
47
  # @return [Class]
45
-
46
- # @private
47
- #
48
- # Build one method from definition
49
- #
50
- # @param definition [MethodDefinition] the method definition
51
- # @param type [Symbol] type of method to be built
52
- #
53
- # @return (see Base#build)
54
- def build_from_definition(definition, type)
55
- if definition.string?
56
- StringMethodBuilder.new(klass, definition, type: type).build
57
- elsif definition.block?
58
- BlockMethodBuilder.new(klass, definition, type: type).build
59
- else
60
- CallMethodBuilder.new(klass, definition, type: type).build
61
- end
62
- end
63
48
  end
64
49
  end
@@ -7,6 +7,8 @@ class Sinclair
7
7
  #
8
8
  # Define a method from block
9
9
  class BlockDefinition < MethodDefinition
10
+ build_with MethodBuilder::BlockMethodBuilder
11
+
10
12
  # @param name [String,Symbol] name of the method
11
13
  # @param block [Proc] block with code to be added as method
12
14
  # @param options [Hash] Options of construction
@@ -7,6 +7,8 @@ class Sinclair
7
7
  #
8
8
  # Define a call of method to e done within the class
9
9
  class CallDefinition < MethodDefinition
10
+ build_with MethodBuilder::CallMethodBuilder
11
+
10
12
  # @param method_name [Symbol] method to be called
11
13
  # @param arguments [Array<Symbol,String>] parameters to be passed as
12
14
  # arguments to the call
@@ -18,35 +20,30 @@ class Sinclair
18
20
  default_value :block?, false
19
21
  default_value :string?, false
20
22
 
21
- # String to be executed within the class
22
- # @return [String]
23
- def code_string
24
- "#{name} :#{arguments.join(', :')}"
25
- end
26
-
27
- # String to be executed within the class running code to change the class itself
23
+ # Block to be evaluated by the class when adding methods
28
24
  #
29
- # @see code_string
30
- # @return [String]
31
- def class_code_string
32
- <<-CODE
33
- class << self
34
- #{code_string}
35
- end
36
- CODE
25
+ # The block will be a call from +method_name+ passing +arguments+
26
+ # as arguments
27
+ # @return [Proc]
28
+ def code_block
29
+ method_name = name
30
+ args = arguments
31
+
32
+ proc do
33
+ send(method_name, *args)
34
+ end
37
35
  end
38
36
 
39
37
  private
40
38
 
41
39
  attr_reader :arguments
42
-
43
40
  # @method arguments
44
41
  # @api private
45
42
  # @private
46
43
  #
47
- # parameters to be passed as arguments to the call
44
+ # Arguments to be passed when calling the method inside the block
48
45
  #
49
- # @return [Array<Symbol,String>]
46
+ # @return [Array<Object>]
50
47
  end
51
48
  end
52
49
  end
@@ -7,6 +7,8 @@ class Sinclair
7
7
  #
8
8
  # Define an instance method from string
9
9
  class StringDefinition < MethodDefinition
10
+ build_with MethodBuilder::StringMethodBuilder
11
+
10
12
  # @param name [String,Symbol] name of the method
11
13
  # @param code [String] code to be evaluated as method
12
14
  # @param options [Hash] Options of construction
@@ -11,7 +11,8 @@ class Sinclair
11
11
  autoload :BlockHelper, 'sinclair/method_definition/block_helper'
12
12
  autoload :BlockDefinition, 'sinclair/method_definition/block_definition'
13
13
  autoload :StringDefinition, 'sinclair/method_definition/string_definition'
14
- autoload :CallDefinition, 'sinclair/method_definition/call_definition'
14
+
15
+ autoload :CallDefinition, 'sinclair/method_definition/call_definition'
15
16
 
16
17
  # @method name
17
18
  #
@@ -59,13 +60,47 @@ class Sinclair
59
60
  # The creation is based on type which will be used to infer
60
61
  # which subclass of {Sinclair::MethodDefinition} to be used
61
62
  #
63
+ # If type is +nil+ then call is delegated to {.from} which will infer the type
64
+ # from the arguments
65
+ #
62
66
  # @param type [Symbol] the method definition type
63
67
  #
64
68
  # @return [Sinclair::MethodDefinition] an instance of a subclass
65
69
  def for(type, *args, **options, &block)
70
+ return from(*args, **options, &block) unless type
71
+
66
72
  klass = const_get("#{type}_definition".camelize)
67
73
  klass.new(*args, **options, &block)
68
74
  end
75
+
76
+ # Defines builder for a definition class
77
+ #
78
+ # @param builder_class [Class<MethodBuilder>]
79
+ #
80
+ # @return [Symbol] constant +:build+
81
+ #
82
+ # @!macro build_with
83
+ # @api private
84
+ #
85
+ # @!method build(klass, type)
86
+ #
87
+ # Builds the method defined
88
+ #
89
+ # The method is built using {$1}
90
+ #
91
+ # @param klass [Class] The class where the method will be built
92
+ # @param type [Symbol] type of method to be built
93
+ # - {MethodBuilder::CLASS_METHOD} : A class method will be built
94
+ # - {MethodBuilder::INSTANCE_METHOD} : An instance method will be built
95
+ #
96
+ # @see $1#build
97
+ #
98
+ # @return [Symbol] the name of the method built
99
+ def build_with(builder_class)
100
+ define_method(:build) do |klass, type|
101
+ builder_class.build(klass, self, type: type)
102
+ end
103
+ end
69
104
  end
70
105
 
71
106
  # @param name [String,Symbol] name of the method
@@ -87,10 +122,13 @@ class Sinclair
87
122
  #
88
123
  # @example (see MethodDefinition::StringDefinition#build)
89
124
  # @example (see MethodDefinition::BlockDefinition#build)
125
+ # @example (see MethodDefinition::CallDefinition#build)
90
126
  #
91
127
  # @return [Symbol] name of the created method
92
- def build(_klass)
93
- raise 'Build is implemented in subclasses. ' \
128
+ #
129
+ # @raise NotImplementedError
130
+ def build(_klass, _type)
131
+ raise NotImplementedError, 'Build is implemented in subclasses. ' \
94
132
  "Use #{self.class}.from to initialize a proper object"
95
133
  end
96
134
 
@@ -12,37 +12,35 @@ class Sinclair
12
12
  #
13
13
  # The type is decided based in the arguments
14
14
  #
15
- # @param name [String,Symbol] method name
16
- # @param options [Hash] Options of construction
17
- # @option options cached [Boolean] Flag telling to create
18
- # a method with cache
19
- #
20
15
  # @overload add(definition_class, name, code = nil, **options)
16
+ # @param name [String,Symbol] method name
21
17
  # @param code [String] code to be evaluated when the method is ran
18
+ # @param options [Hash] Options of construction
19
+ # @option options cached [Boolean] Flag telling to create
20
+ # a method with cache
22
21
  #
23
22
  # @overload add(definition_class, name, **options, &block)
23
+ # @param name [String,Symbol] method name
24
+ # @param options [Hash] Options of construction
25
+ # @option options cached [Boolean] Flag telling to create
26
+ # a method with cache
24
27
  # @param block [Proc] block to be ran as method
25
28
  #
26
- # @return [Array<MethodDefinition>]
27
- def add(name, code = nil, **options, &block)
28
- definitions << MethodDefinition.from(name, code, **options, &block)
29
- end
30
-
31
- # Builds and adds new definition
32
- #
33
- # The type is decided based on the argument +type+
29
+ # @overload add(type, *args, **options, &block)
30
+ # @param type [Symbol] type of definition
31
+ # - :string -> {MethodDefinition::StringDefinition}
32
+ # - :block -> {MethodDefinition::BlockDefinition}
33
+ # - :call -> {MethodDefinition::CallDefinition}
34
+ # @param options [Hash] Options of construction
35
+ # @option options cached [Boolean] Flag telling to create
36
+ # a method with cache
37
+ # @param block [Proc] block to be ran as method
34
38
  #
35
- # @param type [Symbol] type of definition
36
- # - :string -> {MethodDefinition::StringDefinition}
37
- # - :block -> {MethodDefinition::BlockDefinition}
38
- # - :call -> {MethodDefinition::CallDefinition}
39
- # @param options [Hash] Options of construction
40
- # @option options cached [Boolean] Flag telling to create
41
- # a method with cache
42
- # @param block [Proc] block to be ran as method
39
+ # @see MethodDefinition.for
40
+ # @see MethodDefinition.from
43
41
  #
44
42
  # @return [Array<MethodDefinition>]
45
- def add_definition(type, *args, **options, &block)
43
+ def add(*args, type: nil, **options, &block)
46
44
  definitions << MethodDefinition.for(type, *args, **options, &block)
47
45
  end
48
46
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '1.10.0'
4
+ VERSION = '1.11.0'
5
5
  end
data/lib/sinclair.rb CHANGED
@@ -179,107 +179,193 @@ class Sinclair
179
179
  end
180
180
 
181
181
  # Add a method to the method list to be created on klass instances
182
- #
183
- # @param name [String,Symbol] name of the method to be added
184
- # @param options [Hash] Options of construction
185
- # @option options cached [Boolean] Flag telling to create
186
- # a method with cache
182
+ # @see MethodDefinitions#add
187
183
  #
188
184
  # @overload add_method(name, code, **options)
185
+ # @param name [String,Symbol] name of the method to be added
189
186
  # @param code [String] code to be evaluated when the method is ran
187
+ # @param options [Hash] Options of construction
188
+ # @option options cached [Boolean] Flag telling to create
189
+ # a method with cache
190
+ # @see MethodDefinition::StringDefinition
191
+ #
192
+ # @example Using string code to add a string defined method
193
+ # class Person
194
+ # attr_accessor :first_name, :last_name
195
+ #
196
+ # def initialize(first_name, last_name)
197
+ # @first_name = first_name
198
+ # @last_name = last_name
199
+ # end
200
+ # end
201
+ #
202
+ # builder = Sinclair.new(Person)
203
+ # builder.add_method(:full_name, '[first_name, last_name].join(" ")')
204
+ # builder.build
205
+ #
206
+ # Person.new('john', 'wick').full_name # returns 'john wick'
190
207
  #
191
208
  # @overload add_method(name, **options, &block)
209
+ # @param name [String,Symbol] name of the method to be added
192
210
  # @param block [Proc] block to be ran as method
211
+ # @param options [Hash] Options of construction
212
+ # @option options cached [Boolean] Flag telling to create
213
+ # a method with cache
214
+ # @see MethodDefinition::BlockDefinition
215
+ #
216
+ # @example Using block to add a block method
217
+ # class Person
218
+ # attr_accessor :first_name, :last_name
219
+ #
220
+ # def initialize(first_name, last_name)
221
+ # @first_name = first_name
222
+ # @last_name = last_name
223
+ # end
224
+ # end
193
225
  #
194
- # @example Using string code
195
- # class Person
196
- # attr_reader :first_name, :last_name
197
- #
198
- # def initialize(first_name, last_name)
199
- # @first_name = first_name
200
- # @last_name = last_name
226
+ # builder = Sinclair.new(Person)
227
+ # builder.add_method(:bond_name) { "#{last_name}, #{first_name} #{last_name}" }
228
+ # builder.build
229
+ #
230
+ # Person.new('john', 'wick').bond_name # returns 'wick, john wick'
231
+ #
232
+ # @overload add_method(*args, type:, **options, &block)
233
+ # @param args [Array<Object>] arguments to be passed to the definition
234
+ # @param type [Symbol] type of method definition
235
+ # @param block [Proc] block to be ran as method when type is block
236
+ # @param options [Hash] Options of construction
237
+ # @option options cached [Boolean] Flag telling to create
238
+ # a method with cache
239
+ # @see MethodDefinition::BlockDefinition
240
+ # @see MethodDefinition::StringDefinition
241
+ # @see MethodDefinition::CallDefinition
242
+ #
243
+ # @example Passing type block
244
+ # class Person
245
+ # attr_accessor :first_name, :last_name
246
+ #
247
+ # def initialize(first_name, last_name)
248
+ # @first_name = first_name
249
+ # @last_name = last_name
250
+ # end
201
251
  # end
202
- # end
203
252
  #
204
- # builder = Sinclair.new(Person)
205
- # builder.add_method(:full_name, '[first_name, last_name].join(" ")')
206
- # builder.build
253
+ # builder = Sinclair.new(Person)
254
+ # builder.add_method(:bond_name, type: :block, cached: true) do
255
+ # "{last_name}, #{first_name} #{last_name}"
256
+ # end
257
+ # builder.build
207
258
  #
208
- # Person.new('john', 'wick').full_name # returns 'john wick'
259
+ # person.Person.new('john', 'wick')
209
260
  #
210
- # @example Using block
211
- # class Person
212
- # attr_reader :first_name, :last_name
261
+ # person.bond_name # returns 'wick, john wick'
262
+ # person.first_name = 'Johny'
263
+ # person.bond_name # returns 'wick, john wick'
213
264
  #
214
- # def initialize(first_name, last_name)
215
- # @first_name = first_name
216
- # @last_name = last_name
265
+ # @example Passing type call
266
+ # class Person
217
267
  # end
218
- # end
219
268
  #
220
- # builder = Sinclair.new(Person)
221
- # builder.add_method(:full_name, '[first_name, last_name].join(" ")')
222
- # builder.add_method(:bond_name) { "#{last_name}, #{full_name}" }
223
- # builder.build
269
+ # builder = Sinclair.new(Person)
270
+ # builder.add_method(:attr_accessor, :bond_name, type: :call)
271
+ # builder.build
224
272
  #
225
- # Person.new('john', 'wick').bond_name # returns 'wick, john wick'
226
- # @return [Array<MethodDefinition>]
227
- def add_method(name, code = nil, **options, &block)
228
- definitions.add(
229
- name, code, **options, &block
230
- )
273
+ # person.bond_name = 'Bond, James Bond'
274
+ # person.bond_name # returns 'Bond, James Bond'
275
+ #
276
+ # @return [Array<MethodDefinition>] the list of all currently defined instance methods
277
+ def add_method(*args, type: nil, **options, &block)
278
+ definitions.add(*args, type: type, **options, &block)
231
279
  end
232
280
 
233
281
  # Add a method to the method list to be created on klass
234
- #
235
- # @param name [String,Symbol] name of the method to be added
236
- # @param options [Hash] Options of construction
237
- # @option options cached [Boolean] Flag telling to create
238
- # a method with cache
282
+ # @see MethodDefinitions#add
239
283
  #
240
284
  # @overload add_class_method(name, code, **options)
285
+ # @param name [String,Symbol] name of the method to be added
241
286
  # @param code [String] code to be evaluated when the method is ran
287
+ # @param options [Hash] Options of construction
288
+ # @option options cached [Boolean] Flag telling to create
289
+ # a method with cache
290
+ #
291
+ # @example Adding a method by String
292
+ # class EnvFetcher
293
+ # end
294
+ #
295
+ # builder = Sinclair.new(EnvFetcher)
296
+ #
297
+ # builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
298
+ # builder.build
299
+ #
300
+ # ENV['HOSTNAME'] = 'myhost'
301
+ #
302
+ # EnvFetcher.hostname # returns 'myhost'
242
303
  #
243
304
  # @overload add_class_method(name, **options, &block)
305
+ # @param name [String,Symbol] name of the method to be added
244
306
  # @param block [Proc] block to be ran as method
307
+ # @param options [Hash] Options of construction
308
+ # @option options cached [Boolean] Flag telling to create
309
+ # a method with cache
245
310
  #
246
- # @example
247
- # class EnvFetcher
248
- # end
311
+ # @example Adding a method by Block
312
+ # class EnvFetcher
313
+ # end
249
314
  #
250
- # builder = Sinclair.new(EnvFetcher)
315
+ # builder = Sinclair.new(EnvFetcher)
251
316
  #
252
- # builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
253
- # builder.build
317
+ # builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
318
+ # builder.build
254
319
  #
255
- # ENV['HOSTNAME'] = 'myhost'
320
+ # ENV['TIMEOUT'] = '300'
256
321
  #
257
- # env_fetcher.hostname # returns 'myhost'
322
+ # EnvFetcher.timeout # returns '300'
258
323
  #
259
- # @example
260
- # class EnvFetcher
261
- # end
324
+ # @overload add_class_method(*args, type: **options, &block)
325
+ # @param args [Array<Object>] arguments to be passed to the definition
326
+ # @param type [Symbol] type of method definition
327
+ # @param block [Proc] block to be ran as method when type is block
328
+ # @param options [Hash] Options of construction
329
+ # @option options cached [Boolean] Flag telling to create
330
+ # a method with cache
331
+ # @see MethodDefinition::BlockDefinition
332
+ # @see MethodDefinition::StringDefinition
333
+ # @see MethodDefinition::CallDefinition
262
334
  #
263
- # builder = Sinclair.new(EnvFetcher)
335
+ # @example Passing type block
336
+ # class EnvFetcher
337
+ # end
264
338
  #
265
- # builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
266
- # builder.build
339
+ # builder = Sinclair.new(EnvFetcher)
267
340
  #
268
- # ENV['TIMEOUT'] = '300'
341
+ # builder.add_class_method(:timeout, type: :block) { ENV['TIMEOUT'] }
342
+ # builder.build
269
343
  #
270
- # env_fetcher.timeout # returns '300'
344
+ # ENV['TIMEOUT'] = '300'
271
345
  #
272
- # @return [Array<MethodDefinition>]
273
- def add_class_method(name, code = nil, **options, &block)
274
- class_definitions.add(
275
- name, code, **options, &block
276
- )
346
+ # EnvFetcher.timeout # returns '300'
347
+ #
348
+ # @example Passing type call
349
+ # class EnvFetcher
350
+ # end
351
+ #
352
+ # builder = Sinclair.new(EnvFetcher)
353
+ #
354
+ # builder.add_class_method(:attr_accessor, :timeout, type: :call)
355
+ # builder.build
356
+ #
357
+ # EnvFetcher.timeout = 10
358
+ #
359
+ # env_fetcher.timeout # returns '10'
360
+ #
361
+ # @return [Array<MethodDefinition>] the list of all currently defined class methods
362
+ def add_class_method(*args, type: nil, **options, &block)
363
+ class_definitions.add(*args, type: type, **options, &block)
277
364
  end
278
365
 
279
366
  # Evaluetes a block which will result in a String, the method code
280
367
  #
281
368
  # @example Building a initial value class method
282
- #
283
369
  # module InitialValuer
284
370
  # extend ActiveSupport::Concern
285
371
  #
@@ -301,6 +387,7 @@ class Sinclair
301
387
  # end
302
388
  #
303
389
  # object = MyClass.new
390
+ #
304
391
  # object.age # 20
305
392
  # object.age = 30
306
393
  # object.age # 30
@@ -345,7 +432,7 @@ class Sinclair
345
432
  # end
346
433
  #
347
434
  # Purchase.new(2.3, 5).total_price # returns 11.5
348
- # @return [Array<MethodDefinition>]
435
+ # @return [Array<MethodDefinition>] the list of all currently defined instance methods
349
436
  def eval_and_add_method(name, &block)
350
437
  add_method(name, instance_eval(&block))
351
438
  end