sinclair 1.11.0 → 1.12.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|