sinclair 1.11.0 → 1.12.1
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/README.md +42 -12
- data/config/check_specs.yml +2 -2
- data/config/yardstick.yml +2 -0
- data/lib/sinclair/method_builder/base.rb +15 -0
- data/lib/sinclair/method_builder/block_method_builder.rb +1 -12
- data/lib/sinclair/method_builder/call_method_builder.rb +0 -17
- data/lib/sinclair/method_builder/string_method_builder.rb +2 -29
- data/lib/sinclair/method_builder.rb +2 -3
- data/lib/sinclair/method_definition/parameter_builder.rb +89 -0
- data/lib/sinclair/method_definition/parameter_helper.rb +124 -0
- data/lib/sinclair/method_definition/string_definition.rb +24 -2
- data/lib/sinclair/method_definition.rb +3 -2
- data/lib/sinclair/version.rb +1 -1
- data/spec/integration/readme/sinclair/types_of_definition_spec.rb +14 -0
- data/spec/lib/sinclair/method_builder/string_method_builder_spec.rb +24 -1
- data/spec/lib/sinclair/method_definition/parameter_builder_spec.rb +81 -0
- data/spec/lib/sinclair/method_definition/parameter_helper_spec.rb +47 -0
- data/spec/lib/sinclair/method_definition/string_definition_spec.rb +60 -29
- data/spec/lib/sinclair/method_definition_spec.rb +12 -2
- data/spec/support/models/dummy_builder.rb +1 -0
- data/spec/support/models/dummy_class_builder.rb +1 -0
- data/spec/support/shared_examples/sinclair.rb +6 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b14d0d24d28075129d870b9f2b93c306e894407a70878d7950e0c73e7f747dbb
|
4
|
+
data.tar.gz: 5a3d836d3b8eb5dc299dd17836e50f387fe3273820e91ef95581aac25348407d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6bbf090685049aaa1936e632ed420060ccead6071bb9864de3b5e26f16ad68431b6d01de24442f4ac4ce87792158a5def414680fe9d6b941d4031b766bd386e
|
7
|
+
data.tar.gz: ef28a8f5b9f5b9e9e12cd36c558fe2bb14fededbea91df46cda1b2d8570d0fec22809dc3e36f4af61844da370ea659463df03562232883121d0ebc7f40a63e81
|
data/README.md
CHANGED
@@ -13,13 +13,13 @@ This gem helps the creation of complex gems/concerns
|
|
13
13
|
that enables creation of methods on the fly through class
|
14
14
|
methods
|
15
15
|
|
16
|
-
Current Release: [1.
|
16
|
+
Current Release: [1.12.1](https://github.com/darthjee/sinclair/tree/1.12.1)
|
17
17
|
|
18
|
-
[Next release](https://github.com/darthjee/sinclair/compare/1.
|
18
|
+
[Next release](https://github.com/darthjee/sinclair/compare/1.12.1...master)
|
19
19
|
|
20
20
|
Yard Documentation
|
21
21
|
-------------------
|
22
|
-
[https://www.rubydoc.info/gems/sinclair/1.
|
22
|
+
[https://www.rubydoc.info/gems/sinclair/1.12.1](https://www.rubydoc.info/gems/sinclair/1.12.1)
|
23
23
|
|
24
24
|
Installation
|
25
25
|
---------------
|
@@ -270,10 +270,14 @@ invalid_object.valid? # returns false
|
|
270
270
|
</details>
|
271
271
|
|
272
272
|
#### Different ways of adding the methods
|
273
|
-
There are different ways to add a method
|
273
|
+
There are different ways to add a method, each accepting different options
|
274
|
+
|
274
275
|
<details>
|
275
276
|
<summary>Define method using block</summary>
|
276
277
|
|
278
|
+
Block methods accepts, as option
|
279
|
+
- [cache](#caching-the-result): defining the cashing of results
|
280
|
+
|
277
281
|
```ruby
|
278
282
|
klass = Class.new
|
279
283
|
instance = klass.new
|
@@ -289,31 +293,57 @@ instance.random_number # returns a number between 10 and 20
|
|
289
293
|
<details>
|
290
294
|
<summary>Define method using string</summary>
|
291
295
|
|
296
|
+
String methods accepts, as option
|
297
|
+
- [cache](#caching-the-result): defining the cashing of results
|
298
|
+
- parameters: defining accepted parameters
|
299
|
+
- named_parameters: defining accepted named parameters
|
300
|
+
|
292
301
|
```ruby
|
293
|
-
|
294
|
-
instance = klass.new
|
302
|
+
# Example without parameters
|
295
303
|
|
296
|
-
|
304
|
+
class MyClass
|
305
|
+
end
|
306
|
+
instance = MyClass.new
|
307
|
+
|
308
|
+
builder = Sinclair.new(MyClass)
|
297
309
|
builder.add_method(:random_number, "Random.rand(10..20)")
|
298
310
|
builder.build
|
299
311
|
|
300
312
|
instance.random_number # returns a number between 10 and 20
|
301
313
|
```
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
# Example with parameters
|
317
|
+
|
318
|
+
class MyClass
|
319
|
+
end
|
320
|
+
|
321
|
+
builder = described_class.new(MyClass)
|
322
|
+
builder.add_class_method(
|
323
|
+
:function, 'a ** b + c', parameters: [:a], named_parameters: [:b, { c: 15 }]
|
324
|
+
)
|
325
|
+
builder.build
|
326
|
+
|
327
|
+
MyClass.function(10, b: 2) # returns 115
|
328
|
+
```
|
302
329
|
</details>
|
303
330
|
|
304
331
|
<details>
|
305
332
|
<summary>Define method using a call to the class</summary>
|
306
333
|
|
334
|
+
Call method definitions right now have no options available
|
335
|
+
|
307
336
|
```ruby
|
308
|
-
|
337
|
+
class MyClass
|
338
|
+
end
|
309
339
|
|
310
|
-
builder = Sinclair.new(
|
340
|
+
builder = Sinclair.new(MyClass)
|
311
341
|
builder.add_class_method(:attr_accessor, :number, type: :call)
|
312
342
|
builder.build
|
313
343
|
|
314
|
-
|
315
|
-
|
316
|
-
|
344
|
+
MyClass.number # returns nil
|
345
|
+
MyClass.number = 10
|
346
|
+
MyClass.number # returns 10
|
317
347
|
```
|
318
348
|
</details>
|
319
349
|
|
data/config/check_specs.yml
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
ignore:
|
2
2
|
- lib/sinclair/comparable/class_methods.rb
|
3
3
|
- lib/sinclair/exception.rb
|
4
|
-
- lib/sinclair/matchers/add_method_to.rb
|
5
4
|
- lib/sinclair/matchers/add_method.rb
|
5
|
+
- lib/sinclair/matchers/add_method_to.rb
|
6
6
|
- lib/sinclair/matchers/base.rb
|
7
|
-
- lib/sinclair/matchers/method_to.rb
|
8
7
|
- lib/sinclair/matchers/change_method_on.rb
|
8
|
+
- lib/sinclair/matchers/method_to.rb
|
9
9
|
- lib/sinclair/version.rb
|
data/config/yardstick.yml
CHANGED
@@ -60,6 +60,8 @@ rules:
|
|
60
60
|
- Sinclair::MethodDefinition#initialize
|
61
61
|
- Sinclair::MethodDefinition::CallDefinition#initialize
|
62
62
|
- Sinclair::MethodDefinition::BlockDefinition#initialize
|
63
|
+
- Sinclair::MethodDefinition::ParameterBuilder#initialize
|
64
|
+
- Sinclair::MethodDefinition::ParameterHelper#initialize
|
63
65
|
- Sinclair::MethodDefinition::StringDefinition#initialize
|
64
66
|
- Sinclair::Options#initialize
|
65
67
|
- Sinclair::Options::Builder#initialize
|
@@ -77,6 +77,21 @@ class Sinclair
|
|
77
77
|
def instance?
|
78
78
|
type == INSTANCE_METHOD
|
79
79
|
end
|
80
|
+
|
81
|
+
# Returns the klass where the proc block will be evaluated
|
82
|
+
#
|
83
|
+
# For instance type, the class itself is returned
|
84
|
+
#
|
85
|
+
# For adding class methods, the superclass is returned
|
86
|
+
#
|
87
|
+
# @return [Class]
|
88
|
+
def evaluating_class
|
89
|
+
return klass if instance?
|
90
|
+
|
91
|
+
class << klass
|
92
|
+
return self
|
93
|
+
end
|
94
|
+
end
|
80
95
|
end
|
81
96
|
end
|
82
97
|
end
|
@@ -14,21 +14,10 @@ class Sinclair
|
|
14
14
|
#
|
15
15
|
# @return (see Base#build)
|
16
16
|
def build
|
17
|
-
|
17
|
+
evaluating_class.define_method(name, method_block)
|
18
18
|
end
|
19
19
|
|
20
|
-
private
|
21
|
-
|
22
20
|
delegate :name, :method_block, to: :definition
|
23
|
-
|
24
|
-
# @private
|
25
|
-
#
|
26
|
-
# name of the method used to define a new method on class
|
27
|
-
#
|
28
|
-
# @return [Symbol]
|
29
|
-
def method_definition
|
30
|
-
instance? ? :define_method : :define_singleton_method
|
31
|
-
end
|
32
21
|
end
|
33
22
|
end
|
34
23
|
end
|
@@ -19,8 +19,6 @@ class Sinclair
|
|
19
19
|
evaluating_class.module_eval(&code_block)
|
20
20
|
end
|
21
21
|
|
22
|
-
private
|
23
|
-
|
24
22
|
delegate :code_block, to: :definition
|
25
23
|
# @method code_block
|
26
24
|
# @api private
|
@@ -29,21 +27,6 @@ class Sinclair
|
|
29
27
|
# Code block to be evaluated by the class
|
30
28
|
#
|
31
29
|
# @return [Proc]
|
32
|
-
|
33
|
-
# Returns the klass where the proc block will be evaluated
|
34
|
-
#
|
35
|
-
# For instance type, the class itself is returned
|
36
|
-
#
|
37
|
-
# For adding class methods, the superclass is returned
|
38
|
-
#
|
39
|
-
# @return [Class]
|
40
|
-
def evaluating_class
|
41
|
-
return klass if instance?
|
42
|
-
|
43
|
-
class << klass
|
44
|
-
return self
|
45
|
-
end
|
46
|
-
end
|
47
30
|
end
|
48
31
|
end
|
49
32
|
end
|
@@ -14,37 +14,10 @@ class Sinclair
|
|
14
14
|
#
|
15
15
|
# @return (see Base#build)
|
16
16
|
def build
|
17
|
-
|
17
|
+
evaluating_class.module_eval(code_definition, __FILE__, __LINE__ + 1)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
# @private
|
23
|
-
#
|
24
|
-
# string used for method name definition
|
25
|
-
#
|
26
|
-
# the string changes depending if it is
|
27
|
-
# a class or instance method
|
28
|
-
#
|
29
|
-
# @return [String]
|
30
|
-
def definition_name
|
31
|
-
instance? ? name : "self.#{name}"
|
32
|
-
end
|
33
|
-
|
34
|
-
# @private
|
35
|
-
#
|
36
|
-
# string with the code to be defined
|
37
|
-
#
|
38
|
-
# @return [String]
|
39
|
-
def code_definition
|
40
|
-
<<-CODE
|
41
|
-
def #{definition_name}
|
42
|
-
#{code_line}
|
43
|
-
end
|
44
|
-
CODE
|
45
|
-
end
|
46
|
-
|
47
|
-
delegate :code_line, :name, to: :definition
|
20
|
+
delegate :code_definition, to: :definition
|
48
21
|
end
|
49
22
|
end
|
50
23
|
end
|
@@ -7,10 +7,9 @@ class Sinclair
|
|
7
7
|
# Class responsible for building methods
|
8
8
|
class MethodBuilder
|
9
9
|
autoload :Base, 'sinclair/method_builder/base'
|
10
|
-
autoload :StringMethodBuilder, 'sinclair/method_builder/string_method_builder'
|
11
10
|
autoload :BlockMethodBuilder, 'sinclair/method_builder/block_method_builder'
|
12
|
-
|
13
|
-
autoload :
|
11
|
+
autoload :CallMethodBuilder, 'sinclair/method_builder/call_method_builder'
|
12
|
+
autoload :StringMethodBuilder, 'sinclair/method_builder/string_method_builder'
|
14
13
|
|
15
14
|
CLASS_METHOD = :class
|
16
15
|
INSTANCE_METHOD = :instance
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
class MethodDefinition
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Builder a string of parameters
|
9
|
+
#
|
10
|
+
# This is used when creating the string for a method defined
|
11
|
+
# using a string definition
|
12
|
+
#
|
13
|
+
# @see StringDefinition
|
14
|
+
class ParameterBuilder
|
15
|
+
# Builds a string representing method parameters
|
16
|
+
#
|
17
|
+
# @overload from(parameters, named_parameters)
|
18
|
+
# @param parameters [Array<Object>] List of parameters.
|
19
|
+
# @param named_parameters [Array<Object>] List of named parameters
|
20
|
+
#
|
21
|
+
# The list of +parameters+/+named_parameters+ is formed by an
|
22
|
+
# array of +Symbol+ representing required parameters
|
23
|
+
# and +Hash+ representing parameters with default values
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
def self.from(*args)
|
27
|
+
new(*args).to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
private_class_method :new
|
31
|
+
|
32
|
+
# @param parameters [Array<Object>] List of parameters.
|
33
|
+
# @param named_parameters [Array<Object>] List of named parameters
|
34
|
+
def initialize(parameters, named_parameters)
|
35
|
+
@parameters = parameters
|
36
|
+
@named_parameters = named_parameters
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the parameters string
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
def to_s
|
43
|
+
return '' if empty_parameters?
|
44
|
+
|
45
|
+
"(#{parameters_string})"
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
attr_reader :parameters, :named_parameters
|
51
|
+
|
52
|
+
# @!method parameters
|
53
|
+
# @api private
|
54
|
+
# @private
|
55
|
+
#
|
56
|
+
# List of parameters
|
57
|
+
#
|
58
|
+
# @return [Array<Object>]
|
59
|
+
|
60
|
+
# @!method named_parameters
|
61
|
+
# @api private
|
62
|
+
# @private
|
63
|
+
#
|
64
|
+
# List of named parameters
|
65
|
+
#
|
66
|
+
# @return [Array<Object>]
|
67
|
+
|
68
|
+
# @private
|
69
|
+
# Flag if any kind of parameters have not been provided
|
70
|
+
#
|
71
|
+
# @return [TrueClass,FalseClass]
|
72
|
+
def empty_parameters?
|
73
|
+
!parameters.present? && !named_parameters.present?
|
74
|
+
end
|
75
|
+
|
76
|
+
# String of parameters witout ()
|
77
|
+
#
|
78
|
+
# This will join all individual parameters strings by +,+
|
79
|
+
#
|
80
|
+
# @return [String]
|
81
|
+
def parameters_string
|
82
|
+
(
|
83
|
+
ParameterHelper.parameters_from(parameters) +
|
84
|
+
ParameterHelper.parameters_from(named_parameters, named: true)
|
85
|
+
).join(', ')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
class MethodDefinition
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Helper containing helepr methods for remapping parameters
|
9
|
+
#
|
10
|
+
# @see ParameterBuilder
|
11
|
+
class ParameterHelper
|
12
|
+
# Returns a list of strings of parameters
|
13
|
+
#
|
14
|
+
# @overload parameters_from(parameters_list, named: false)
|
15
|
+
# @param parameters_list [Array<Object>] list of parameters and defaults
|
16
|
+
# @param named [TrueClass,FalseClass] Flag informing if the parameters are
|
17
|
+
# named parameters
|
18
|
+
#
|
19
|
+
# @return [String]
|
20
|
+
def self.parameters_from(*args, **opts)
|
21
|
+
new(*args, **opts).strings
|
22
|
+
end
|
23
|
+
|
24
|
+
private_class_method :new
|
25
|
+
|
26
|
+
# @param parameters_list [Array<Object>] list of parameters and defaults
|
27
|
+
# @param named [TrueClass,FalseClass] Flag informing if the parameters are
|
28
|
+
# named parameters
|
29
|
+
def initialize(parameters_list, named: false)
|
30
|
+
@parameters_list = parameters_list
|
31
|
+
@named = named
|
32
|
+
end
|
33
|
+
|
34
|
+
# All parameters converted into strings
|
35
|
+
#
|
36
|
+
# The strings are ready to be pushed into a method definition
|
37
|
+
# and joined by +,+
|
38
|
+
#
|
39
|
+
# @return [Array<String>]
|
40
|
+
def strings
|
41
|
+
return [] unless parameters_list
|
42
|
+
|
43
|
+
parameters_strings + defaults_strings
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :parameters_list, :named
|
49
|
+
alias named? named
|
50
|
+
|
51
|
+
# @!method parameters_list
|
52
|
+
# @api private
|
53
|
+
# @private
|
54
|
+
#
|
55
|
+
# List of parameters and parameters with defaults
|
56
|
+
#
|
57
|
+
# @return [Array<Object>]
|
58
|
+
|
59
|
+
# @!method named
|
60
|
+
# @api private
|
61
|
+
# @private
|
62
|
+
#
|
63
|
+
# Flag informing if the parameters are named parameters
|
64
|
+
#
|
65
|
+
# @return [TrueClass,FalseClass]
|
66
|
+
|
67
|
+
# @!method named?
|
68
|
+
# @api private
|
69
|
+
# @private
|
70
|
+
#
|
71
|
+
# Flag informing if the parameters are named parameters
|
72
|
+
#
|
73
|
+
# @return [TrueClass,FalseClass]
|
74
|
+
|
75
|
+
# Parameters without defaults
|
76
|
+
#
|
77
|
+
# These are filtered out from {#parameters_list} where they are not
|
78
|
+
# of type +Hash+
|
79
|
+
#
|
80
|
+
# @return [Array<Symbol>]
|
81
|
+
def parameters
|
82
|
+
parameters_list.reject do |param|
|
83
|
+
param.is_a?(Hash)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Hash representing all parameters with default values
|
88
|
+
#
|
89
|
+
# These are filtered out from {#parameters_list} where they are
|
90
|
+
# of type +Hash+ and merged into a single hash
|
91
|
+
#
|
92
|
+
# @return [Hash]
|
93
|
+
def defaults
|
94
|
+
parameters_list.select do |param|
|
95
|
+
param.is_a?(Hash)
|
96
|
+
end.reduce(&:merge) || {}
|
97
|
+
end
|
98
|
+
|
99
|
+
# Parameters without default converted to final string
|
100
|
+
#
|
101
|
+
# {#extra} is added so that for normal parameters the parameter is returned
|
102
|
+
# and for named parameter +:+ is added
|
103
|
+
#
|
104
|
+
# @return [Array<String>]
|
105
|
+
def parameters_strings
|
106
|
+
return parameters.map(&:to_s) unless named?
|
107
|
+
|
108
|
+
parameters.map do |param|
|
109
|
+
"#{param}:"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Strings representing all parameters with default value
|
114
|
+
#
|
115
|
+
# @return [Array<String>]
|
116
|
+
def defaults_strings
|
117
|
+
joinner = named? ? ': ' : ' = '
|
118
|
+
defaults.map do |key, value|
|
119
|
+
"#{key}#{joinner}#{value.to_json}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -22,6 +22,30 @@ class Sinclair
|
|
22
22
|
default_value :block?, false
|
23
23
|
default_value :string?, true
|
24
24
|
|
25
|
+
# string with the code to be defined
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
def code_definition
|
29
|
+
<<-CODE
|
30
|
+
def #{name}#{parameters_string}
|
31
|
+
#{code_line}
|
32
|
+
end
|
33
|
+
CODE
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# @private
|
39
|
+
# String for parameters
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
def parameters_string
|
43
|
+
ParameterBuilder.from(
|
44
|
+
options_object.parameters, options_object.named_parameters
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @private
|
25
49
|
# codeline to be run inside the code
|
26
50
|
#
|
27
51
|
# @return [String]
|
@@ -29,8 +53,6 @@ class Sinclair
|
|
29
53
|
cached? ? code_with_cache : code
|
30
54
|
end
|
31
55
|
|
32
|
-
private
|
33
|
-
|
34
56
|
# @method code
|
35
57
|
# @private
|
36
58
|
#
|
@@ -10,9 +10,10 @@ class Sinclair
|
|
10
10
|
|
11
11
|
autoload :BlockHelper, 'sinclair/method_definition/block_helper'
|
12
12
|
autoload :BlockDefinition, 'sinclair/method_definition/block_definition'
|
13
|
+
autoload :CallDefinition, 'sinclair/method_definition/call_definition'
|
13
14
|
autoload :StringDefinition, 'sinclair/method_definition/string_definition'
|
14
|
-
|
15
|
-
autoload :
|
15
|
+
autoload :ParameterBuilder, 'sinclair/method_definition/parameter_builder'
|
16
|
+
autoload :ParameterHelper, 'sinclair/method_definition/parameter_helper'
|
16
17
|
|
17
18
|
# @method name
|
18
19
|
#
|
data/lib/sinclair/version.rb
CHANGED
@@ -30,6 +30,20 @@ describe Sinclair do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
describe 'Define method using string with parameters' do
|
34
|
+
it 'adds the method' do
|
35
|
+
klass = Class.new
|
36
|
+
|
37
|
+
builder = described_class.new(klass)
|
38
|
+
builder.add_class_method(
|
39
|
+
:function, 'a ** b + c', parameters: [:a], named_parameters: [:b, { c: 15 }]
|
40
|
+
)
|
41
|
+
builder.build
|
42
|
+
|
43
|
+
expect(klass.function(10, b: 2)).to eq(115)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
33
47
|
describe 'Define method using call to the class' do
|
34
48
|
it 'performs the call to the class' do
|
35
49
|
klass = Class.new
|
@@ -12,9 +12,11 @@ describe Sinclair::MethodBuilder::StringMethodBuilder do
|
|
12
12
|
let(:instance) { klass.new }
|
13
13
|
let(:value) { Random.rand }
|
14
14
|
let(:method_name) { :the_method }
|
15
|
+
let(:code) { value.to_s }
|
16
|
+
let(:options) { {} }
|
15
17
|
|
16
18
|
let(:definition) do
|
17
|
-
Sinclair::MethodDefinition.from(method_name,
|
19
|
+
Sinclair::MethodDefinition.from(method_name, code, **options)
|
18
20
|
end
|
19
21
|
|
20
22
|
context 'when type is instance' do
|
@@ -31,6 +33,27 @@ describe Sinclair::MethodBuilder::StringMethodBuilder do
|
|
31
33
|
it 'returns the result of the code when called' do
|
32
34
|
expect(instance.the_method).to eq(value)
|
33
35
|
end
|
36
|
+
|
37
|
+
it 'creates a method with no parameters' do
|
38
|
+
expect(instance.method(method_name).parameters)
|
39
|
+
.to be_empty
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when the method is built with parameters' do
|
44
|
+
let(:code) { 'a + b' }
|
45
|
+
let(:options) { { parameters: %i[a b] } }
|
46
|
+
|
47
|
+
before { builder.build }
|
48
|
+
|
49
|
+
it 'returns the result of the code when called' do
|
50
|
+
expect(instance.the_method(12, 23)).to eq(35)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'creates a method with no parameters' do
|
54
|
+
expect(instance.method(method_name).parameters)
|
55
|
+
.to eq([%i[req a], %i[req b]])
|
56
|
+
end
|
34
57
|
end
|
35
58
|
end
|
36
59
|
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::MethodDefinition::ParameterBuilder do
|
6
|
+
describe '.from' do
|
7
|
+
let(:parameters) { nil }
|
8
|
+
let(:named_parameters) { nil }
|
9
|
+
|
10
|
+
context 'when parameters and named_parameters are nil' do
|
11
|
+
it do
|
12
|
+
expect(described_class.from(parameters, named_parameters))
|
13
|
+
.to eq('')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when parameters is empty' do
|
18
|
+
let(:parameters) { [] }
|
19
|
+
|
20
|
+
it do
|
21
|
+
expect(described_class.from(parameters, named_parameters))
|
22
|
+
.to eq('')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when named_parameters is empty' do
|
27
|
+
let(:named_parameters) { [] }
|
28
|
+
|
29
|
+
it do
|
30
|
+
expect(described_class.from(parameters, named_parameters))
|
31
|
+
.to eq('')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when parameters has no default values' do
|
36
|
+
let(:parameters) { %i[x y] }
|
37
|
+
|
38
|
+
it do
|
39
|
+
expect(described_class.from(parameters, named_parameters))
|
40
|
+
.to eq('(x, y)')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when named_parameters has no default values' do
|
45
|
+
let(:named_parameters) { %i[x y] }
|
46
|
+
|
47
|
+
it do
|
48
|
+
expect(described_class.from(parameters, named_parameters))
|
49
|
+
.to eq('(x:, y:)')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when parameters has only default values' do
|
54
|
+
let(:parameters) { [{ x: 1, y: 3 }] }
|
55
|
+
|
56
|
+
it do
|
57
|
+
expect(described_class.from(parameters, named_parameters))
|
58
|
+
.to eq('(x = 1, y = 3)')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when named parameters has only default values' do
|
63
|
+
let(:named_parameters) { [{ x: 1, y: 3 }] }
|
64
|
+
|
65
|
+
it do
|
66
|
+
expect(described_class.from(parameters, named_parameters))
|
67
|
+
.to eq('(x: 1, y: 3)')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when all options are present' do
|
72
|
+
let(:parameters) { [:x, { y: 2 }] }
|
73
|
+
let(:named_parameters) { [:a, { b: 3 }] }
|
74
|
+
|
75
|
+
it do
|
76
|
+
expect(described_class.from(parameters, named_parameters))
|
77
|
+
.to eq('(x, y = 2, a:, b: 3)')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::MethodDefinition::ParameterHelper do
|
6
|
+
describe '.parameters_from' do
|
7
|
+
context 'when parameters are not named' do
|
8
|
+
context 'when there are no defaults' do
|
9
|
+
it 'returns a list of parameters' do
|
10
|
+
expect(described_class.parameters_from(%i[a b]))
|
11
|
+
.to eq(%w[a b])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when there are defaults' do
|
16
|
+
let(:parameters) do
|
17
|
+
[{ a: 10, b: 'word', c: true, d: false }]
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns a list of parameters' do
|
21
|
+
expect(described_class.parameters_from(parameters))
|
22
|
+
.to eq(['a = 10', 'b = "word"', 'c = true', 'd = false'])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when parameters are named' do
|
28
|
+
context 'when there are no defaults' do
|
29
|
+
it 'returns a list of parameters' do
|
30
|
+
expect(described_class.parameters_from(%i[a b], named: true))
|
31
|
+
.to eq(%w[a: b:])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when there are defaults' do
|
36
|
+
let(:parameters) do
|
37
|
+
[{ a: 10, b: 'word', c: true, d: false }]
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns a list of parameters' do
|
41
|
+
expect(described_class.parameters_from(parameters, named: true))
|
42
|
+
.to eq(['a: 10', 'b: "word"', 'c: true', 'd: false'])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -11,59 +11,90 @@ describe Sinclair::MethodDefinition::StringDefinition do
|
|
11
11
|
let(:code) { 'Random.rand' }
|
12
12
|
let(:options) { {} }
|
13
13
|
|
14
|
-
describe '#
|
15
|
-
let(:klass)
|
16
|
-
let(:instance)
|
17
|
-
let(:
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
describe '#code_definition' do
|
15
|
+
let(:klass) { Class.new }
|
16
|
+
let(:instance) { klass.new }
|
17
|
+
let(:code_definition) { definition.code_definition }
|
18
|
+
let(:expected_code) do
|
19
|
+
<<-CODE
|
20
|
+
def #{method_name}
|
21
|
+
#{code}
|
22
|
+
end
|
23
|
+
CODE
|
21
24
|
end
|
22
25
|
|
23
26
|
it 'returns a code with no cache' do
|
24
|
-
expect(
|
25
|
-
.
|
27
|
+
expect(definition.code_definition.gsub(/^ */, ''))
|
28
|
+
.to eq(expected_code.gsub(/^ */, ''))
|
26
29
|
end
|
27
30
|
|
28
|
-
context 'when
|
29
|
-
let(:options) { {
|
31
|
+
context 'when parameters are given with defaults' do
|
32
|
+
let(:options) { { parameters: [:x, { y: 10 }] } }
|
33
|
+
let(:code) { 'x + y' }
|
34
|
+
let(:expected_code) do
|
35
|
+
<<-CODE
|
36
|
+
def #{method_name}(x, y = 10)
|
37
|
+
#{code}
|
38
|
+
end
|
39
|
+
CODE
|
40
|
+
end
|
30
41
|
|
31
42
|
it 'returns the code with simple cache' do
|
32
|
-
expect(definition.
|
33
|
-
.to eq(
|
43
|
+
expect(definition.code_definition.gsub(/^ */, ''))
|
44
|
+
.to eq(expected_code.gsub(/^ */, ''))
|
34
45
|
end
|
46
|
+
end
|
35
47
|
|
36
|
-
|
37
|
-
|
38
|
-
|
48
|
+
context 'when parameters are given' do
|
49
|
+
let(:options) { { parameters: %i[x y] } }
|
50
|
+
let(:code) { 'x + y' }
|
51
|
+
let(:expected_code) do
|
52
|
+
<<-CODE
|
53
|
+
def #{method_name}(x, y)
|
54
|
+
#{code}
|
55
|
+
end
|
56
|
+
CODE
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns the code with simple cache' do
|
60
|
+
expect(definition.code_definition.gsub(/^ */, ''))
|
61
|
+
.to eq(expected_code.gsub(/^ */, ''))
|
39
62
|
end
|
63
|
+
end
|
40
64
|
|
41
|
-
|
42
|
-
|
65
|
+
context 'when cache true is given' do
|
66
|
+
let(:options) { { cached: true } }
|
67
|
+
let(:expected_code) do
|
68
|
+
<<-CODE
|
69
|
+
def #{method_name}
|
70
|
+
@#{method_name} ||= #{code}
|
71
|
+
end
|
72
|
+
CODE
|
73
|
+
end
|
43
74
|
|
44
|
-
|
75
|
+
it 'returns the code with simple cache' do
|
76
|
+
expect(definition.code_definition.gsub(/^ */, ''))
|
77
|
+
.to eq(expected_code.gsub(/^ */, ''))
|
45
78
|
end
|
46
79
|
end
|
47
80
|
|
48
81
|
context 'when cache full is given' do
|
49
82
|
let(:options) { { cached: :full } }
|
50
83
|
let(:expected) do
|
51
|
-
|
84
|
+
<<-CODE
|
85
|
+
def #{method_name}
|
86
|
+
defined?(@#{method_name}) ? @#{method_name} : (@#{method_name} = #{code})
|
87
|
+
end
|
88
|
+
CODE
|
52
89
|
end
|
53
90
|
|
54
91
|
it 'returns the code with full cache' do
|
55
|
-
expect(definition.
|
92
|
+
expect(definition.code_definition.gsub(/^ */, '')).to eq(expected.gsub(/^ */, ''))
|
56
93
|
end
|
57
94
|
|
58
95
|
it 'returns a code with cache' do
|
59
|
-
expect(instance.instance_eval(
|
60
|
-
.to eq(instance.instance_eval(
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'returns a code that caches nil' do
|
64
|
-
instance.instance_variable_set("@#{method_name}", nil)
|
65
|
-
|
66
|
-
expect(instance.instance_eval(code_line)).to be_nil
|
96
|
+
expect(instance.instance_eval(code_definition))
|
97
|
+
.to eq(instance.instance_eval(code_definition))
|
67
98
|
end
|
68
99
|
end
|
69
100
|
end
|
@@ -25,8 +25,18 @@ describe Sinclair::MethodDefinition do
|
|
25
25
|
context 'when the builder has been defined' do
|
26
26
|
let(:definition_class) do
|
27
27
|
Class.new(described_class) do
|
28
|
-
|
29
|
-
|
28
|
+
attr_reader :name
|
29
|
+
|
30
|
+
def initialize(name)
|
31
|
+
@name = name
|
32
|
+
end
|
33
|
+
|
34
|
+
def code_definition
|
35
|
+
<<-CODE
|
36
|
+
def #{name}
|
37
|
+
10
|
38
|
+
end
|
39
|
+
CODE
|
30
40
|
end
|
31
41
|
end
|
32
42
|
end
|
@@ -5,6 +5,7 @@ class Sinclair
|
|
5
5
|
def init
|
6
6
|
add_method(:blocked) { 1 }
|
7
7
|
add_method(:defined, "@value = value + #{options_object&.increment || 1}")
|
8
|
+
add_method(:sum, 'x + y', parameters: %i[x y])
|
8
9
|
add_method(:value, cached: true) { 0 }
|
9
10
|
add_method(:type_block, type: :block) { 3 }
|
10
11
|
add_method(:type_string, '10', type: :string)
|
@@ -5,6 +5,7 @@ class Sinclair
|
|
5
5
|
def init
|
6
6
|
add_class_method(:blocked) { 1 }
|
7
7
|
add_class_method(:defined, "@value = value + #{options_object&.increment || 1}")
|
8
|
+
add_class_method(:sum, 'x + y', parameters: %i[x y])
|
8
9
|
add_class_method(:value, '@value ||= 0')
|
9
10
|
add_class_method(:type_block, type: :block) { 3 }
|
10
11
|
add_class_method(:type_string, '10', type: :string)
|
@@ -26,6 +26,12 @@ RSpec.shared_examples 'A sinclair builder' do |type|
|
|
26
26
|
expect(object.defined).to eq(1)
|
27
27
|
expect(object.defined).to eq(2)
|
28
28
|
end
|
29
|
+
|
30
|
+
context 'when the method has custom parameters' do
|
31
|
+
it 'creates a method using the string definition' do
|
32
|
+
expect(object.sum(10, 23)).to eq(33)
|
33
|
+
end
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
37
|
context 'when describing a method using a block specific type' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinclair
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DarthJee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
11
|
+
date: 2023-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -308,6 +308,8 @@ files:
|
|
308
308
|
- lib/sinclair/method_definition/block_definition.rb
|
309
309
|
- lib/sinclair/method_definition/block_helper.rb
|
310
310
|
- lib/sinclair/method_definition/call_definition.rb
|
311
|
+
- lib/sinclair/method_definition/parameter_builder.rb
|
312
|
+
- lib/sinclair/method_definition/parameter_helper.rb
|
311
313
|
- lib/sinclair/method_definition/string_definition.rb
|
312
314
|
- lib/sinclair/method_definitions.rb
|
313
315
|
- lib/sinclair/options.rb
|
@@ -377,6 +379,8 @@ files:
|
|
377
379
|
- spec/lib/sinclair/method_definition/block_definition_spec.rb
|
378
380
|
- spec/lib/sinclair/method_definition/block_helper_spec.rb
|
379
381
|
- spec/lib/sinclair/method_definition/call_definition_spec.rb
|
382
|
+
- spec/lib/sinclair/method_definition/parameter_builder_spec.rb
|
383
|
+
- spec/lib/sinclair/method_definition/parameter_helper_spec.rb
|
380
384
|
- spec/lib/sinclair/method_definition/string_definition_spec.rb
|
381
385
|
- spec/lib/sinclair/method_definition_spec.rb
|
382
386
|
- spec/lib/sinclair/method_definitions_spec.rb
|