sinclair 1.4.2 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +4 -1
- data/Dockerfile +3 -3
- data/README.md +1 -1
- data/config/check_specs.yml +5 -0
- data/config/yardstick.yml +3 -0
- data/lib/sinclair.rb +26 -9
- data/lib/sinclair/config/methods_builder.rb +3 -1
- data/lib/sinclair/config_factory.rb +4 -2
- data/lib/sinclair/matchers/add_class_method_to.rb +1 -0
- data/lib/sinclair/method_builder.rb +61 -0
- data/lib/sinclair/method_builder/base.rb +67 -0
- data/lib/sinclair/method_builder/block_method_builder.rb +34 -0
- data/lib/sinclair/method_builder/string_method_builder.rb +50 -0
- data/lib/sinclair/method_definition.rb +38 -17
- data/lib/sinclair/method_definition/block_definition.rb +8 -94
- data/lib/sinclair/method_definition/block_helper.rb +46 -0
- data/lib/sinclair/method_definition/string_definition.rb +7 -66
- data/lib/sinclair/method_definitions.rb +16 -4
- data/lib/sinclair/version.rb +1 -1
- data/sinclair.gemspec +1 -1
- data/spec/lib/sinclair/method_builder/block_method_builder_spec.rb +55 -0
- data/spec/lib/sinclair/method_builder/string_method_builder_spec.rb +54 -0
- data/spec/lib/sinclair/method_builder_spec.rb +53 -0
- data/spec/lib/sinclair/method_definition/block_definition_spec.rb +66 -0
- data/spec/lib/sinclair/method_definition/block_helper_spec.rb +111 -0
- data/spec/lib/sinclair/method_definition/string_definition_spec.rb +70 -0
- data/spec/lib/sinclair/method_definition_spec.rb +23 -88
- data/spec/lib/sinclair/method_definitions_spec.rb +45 -0
- data/spec/support/models/random_generator.rb +13 -0
- metadata +18 -20
- data/lib/sinclair/method_definition/class_block_definition.rb +0 -22
- data/lib/sinclair/method_definition/class_method_definition.rb +0 -50
- data/lib/sinclair/method_definition/class_string_definition.rb +0 -24
- data/lib/sinclair/method_definition/instance_block_definition.rb +0 -22
- data/lib/sinclair/method_definition/instance_method_definition.rb +0 -48
- data/lib/sinclair/method_definition/instance_string_definition.rb +0 -24
- data/spec/integration/yard/sinclair/method_definition/class_block_definition_spec.rb +0 -34
- data/spec/integration/yard/sinclair/method_definition/class_method_definition_spec.rb +0 -28
- data/spec/integration/yard/sinclair/method_definition/class_string_definition_spec.rb +0 -23
- data/spec/integration/yard/sinclair/method_definition/instance_block_definition_spec.rb +0 -25
- data/spec/integration/yard/sinclair/method_definition/instance_method_definition_spec.rb +0 -35
- data/spec/integration/yard/sinclair/method_definition/instance_string_definition_spec.rb +0 -32
- data/spec/lib/sinclair/method_definition/class_block_definition_spec.rb +0 -29
- data/spec/lib/sinclair/method_definition/class_string_definition_spec.rb +0 -27
- data/spec/lib/sinclair/method_definition/instance_block_definition_spec.rb +0 -30
- data/spec/lib/sinclair/method_definition/instance_string_definition_spec.rb +0 -28
@@ -17,71 +17,9 @@ class Sinclair
|
|
17
17
|
super(name, **options)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
# @param klass [Class] class which will receive the new method
|
23
|
-
#
|
24
|
-
# @see MethodDefinition#build
|
25
|
-
#
|
26
|
-
# @return [Symbol] name of the created method
|
27
|
-
#
|
28
|
-
# @example Using instance block method with cached options
|
29
|
-
# class MyModel
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# instance = MyModel.new
|
33
|
-
#
|
34
|
-
# method_definition = Sinclair::MethodDefinition::InstanceBlockDefinition.new(
|
35
|
-
# :sequence, cached: true
|
36
|
-
# ) do
|
37
|
-
# @x = @x.to_i ** 2 + 1
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# method_definition.build(MyModel) # adds instance_method :sequence to
|
41
|
-
# # MyModel instances
|
42
|
-
#
|
43
|
-
# instance.instance_variable_get(:@sequence) # returns nil
|
44
|
-
# instance.instance_variable_get(:@x) # returns nil
|
45
|
-
#
|
46
|
-
# instance.sequence # returns 1
|
47
|
-
# instance.sequence # returns 1 (cached value)
|
48
|
-
#
|
49
|
-
# instance.instance_variable_get(:@sequence) # returns 1
|
50
|
-
# instance.instance_variable_get(:@x) # returns 1
|
51
|
-
#
|
52
|
-
# @example Using class block method without options
|
53
|
-
# class MyModel
|
54
|
-
# end
|
55
|
-
#
|
56
|
-
# method_definition = Sinclair::MethodDefinition::ClassBlockDefinition.new(:sequence) do
|
57
|
-
# @x = @x.to_i ** 2 + 1
|
58
|
-
# end
|
59
|
-
#
|
60
|
-
# method_definition.build(MyModel) # adds instance_method :sequence to
|
61
|
-
# # MyModel instances
|
62
|
-
#
|
63
|
-
# MyModel.instance_variable_get(:@x) # returns nil
|
64
|
-
#
|
65
|
-
# MyModel.sequence # returns 1
|
66
|
-
# MyModel.sequence # returns 2
|
67
|
-
# MyModel.sequence # returns 5
|
68
|
-
#
|
69
|
-
# MyModel.instance_variable_get(:@x) # returns 5
|
70
|
-
def build(klass)
|
71
|
-
klass.send(method_definer, name, method_block)
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
20
|
+
default_value :block?, true
|
21
|
+
default_value :string?, false
|
75
22
|
|
76
|
-
# @method block
|
77
|
-
# @private
|
78
|
-
#
|
79
|
-
# Block with code to be added as method
|
80
|
-
# @return [Proc]
|
81
|
-
attr_reader :block
|
82
|
-
|
83
|
-
# @private
|
84
|
-
#
|
85
23
|
# Returns the block that will be used for method creattion
|
86
24
|
#
|
87
25
|
# @return [Proc]
|
@@ -90,44 +28,20 @@ class Sinclair
|
|
90
28
|
|
91
29
|
case cached
|
92
30
|
when :full
|
93
|
-
full_cached_method_proc(name, block)
|
31
|
+
BlockHelper.full_cached_method_proc(name, &block)
|
94
32
|
else
|
95
|
-
cached_method_proc(name, block)
|
33
|
+
BlockHelper.cached_method_proc(name, &block)
|
96
34
|
end
|
97
35
|
end
|
98
36
|
|
99
|
-
|
100
|
-
#
|
101
|
-
# Returns proc block when {#cached?} as simple
|
102
|
-
#
|
103
|
-
# @return [Proc]
|
104
|
-
def cached_method_proc(method_name, inner_block)
|
105
|
-
proc do
|
106
|
-
instance_variable_get("@#{method_name}") ||
|
107
|
-
instance_variable_set(
|
108
|
-
"@#{method_name}",
|
109
|
-
instance_eval(&inner_block)
|
110
|
-
)
|
111
|
-
end
|
112
|
-
end
|
37
|
+
private
|
113
38
|
|
39
|
+
# @method block
|
114
40
|
# @private
|
115
41
|
#
|
116
|
-
#
|
117
|
-
#
|
42
|
+
# Block with code to be added as method
|
118
43
|
# @return [Proc]
|
119
|
-
|
120
|
-
proc do
|
121
|
-
if instance_variable_defined?("@#{method_name}")
|
122
|
-
instance_variable_get("@#{method_name}")
|
123
|
-
else
|
124
|
-
instance_variable_set(
|
125
|
-
"@#{method_name}",
|
126
|
-
instance_eval(&inner_block)
|
127
|
-
)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
44
|
+
attr_reader :block
|
131
45
|
end
|
132
46
|
end
|
133
47
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
class MethodDefinition
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Helper for wrapping block with cacheing
|
9
|
+
module BlockHelper
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# @private
|
13
|
+
#
|
14
|
+
# Returns proc block when {#cached?} as simple
|
15
|
+
#
|
16
|
+
# @return [Proc]
|
17
|
+
def cached_method_proc(method_name, &inner_block)
|
18
|
+
proc do
|
19
|
+
instance_variable_get("@#{method_name}") ||
|
20
|
+
instance_variable_set(
|
21
|
+
"@#{method_name}",
|
22
|
+
instance_eval(&inner_block)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# @private
|
28
|
+
#
|
29
|
+
# Returns proc block when {#cached?} as full
|
30
|
+
#
|
31
|
+
# @return [Proc]
|
32
|
+
def full_cached_method_proc(method_name, &inner_block)
|
33
|
+
proc do
|
34
|
+
if instance_variable_defined?("@#{method_name}")
|
35
|
+
instance_variable_get("@#{method_name}")
|
36
|
+
else
|
37
|
+
instance_variable_set(
|
38
|
+
"@#{method_name}",
|
39
|
+
instance_eval(&inner_block)
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -19,58 +19,14 @@ class Sinclair
|
|
19
19
|
super(name, **options)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
# @see MethodDefinition#build
|
27
|
-
#
|
28
|
-
# @return [Symbol] name of the created method
|
29
|
-
#
|
30
|
-
# @example Using instance string method with no options
|
31
|
-
# class MyModel
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# instance = MyModel.new
|
35
|
-
#
|
36
|
-
# method_definition = Sinclair::MethodDefinition::InstanceStringDefinition.new(
|
37
|
-
# :sequence, '@x = @x.to_i ** 2 + 1'
|
38
|
-
# )
|
39
|
-
#
|
40
|
-
# method_definition.build(MyModel) # adds instance_method :sequence to
|
41
|
-
# # MyModel instances
|
42
|
-
#
|
43
|
-
# instance.instance_variable_get(:@x) # returns nil
|
44
|
-
#
|
45
|
-
# instance.sequence # returns 1
|
46
|
-
# instance.sequence # returns 2
|
47
|
-
# instance.sequence # returns 5
|
48
|
-
#
|
49
|
-
# instance.instance_variable_get(:@x) # returns 5
|
50
|
-
#
|
51
|
-
# @example Using class string method with cache options
|
52
|
-
# class MyModel
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
# method_definition = Sinclair::MethodDefinition::ClassStringDefinition.new(
|
56
|
-
# :sequence,
|
57
|
-
# '@x = @x.to_i ** 2 + 1',
|
58
|
-
# cached: true
|
59
|
-
# )
|
60
|
-
#
|
61
|
-
# method_definition.build(MyModel) # adds instance_method :sequence to
|
62
|
-
# # MyModel instances
|
63
|
-
#
|
64
|
-
# MyModel.instance_variable_get(:@sequence) # returns nil
|
65
|
-
# MyModel.instance_variable_get(:@x) # returns nil
|
66
|
-
#
|
67
|
-
# MyModel.sequence # returns 1
|
68
|
-
# MyModel.sequence # returns 1 (cached value)
|
22
|
+
default_value :block?, false
|
23
|
+
default_value :string?, true
|
24
|
+
|
25
|
+
# codeline to be run inside the code
|
69
26
|
#
|
70
|
-
#
|
71
|
-
|
72
|
-
|
73
|
-
klass.module_eval(code_definition, __FILE__, __LINE__ + 1)
|
27
|
+
# @return [String]
|
28
|
+
def code_line
|
29
|
+
cached? ? code_with_cache : code
|
74
30
|
end
|
75
31
|
|
76
32
|
private
|
@@ -83,21 +39,6 @@ class Sinclair
|
|
83
39
|
# @return [String]
|
84
40
|
attr_reader :code
|
85
41
|
|
86
|
-
# @private
|
87
|
-
#
|
88
|
-
# Builds full code of method
|
89
|
-
#
|
90
|
-
# @return [String]
|
91
|
-
def code_definition
|
92
|
-
code_line = cached? ? code_with_cache : code
|
93
|
-
|
94
|
-
<<-CODE
|
95
|
-
def #{method_name}
|
96
|
-
#{code_line}
|
97
|
-
end
|
98
|
-
CODE
|
99
|
-
end
|
100
|
-
|
101
42
|
# @private
|
102
43
|
#
|
103
44
|
# Returns string code when {#cached?}
|
@@ -5,10 +5,11 @@ class Sinclair
|
|
5
5
|
# @author darthjee
|
6
6
|
#
|
7
7
|
# Enumerator holding all method definitions
|
8
|
-
class MethodDefinitions
|
8
|
+
class MethodDefinitions
|
9
|
+
delegate :each, to: :definitions
|
10
|
+
|
9
11
|
# Builds and adds new definition
|
10
12
|
#
|
11
|
-
# @param definition_class [Class] class used to define method definition
|
12
13
|
# @param name [String,Symbol] method name
|
13
14
|
# @param options [Hash] Options of construction
|
14
15
|
# @option options cached [Boolean] Flag telling to create
|
@@ -21,8 +22,19 @@ class Sinclair
|
|
21
22
|
# @param block [Proc] block to be ran as method
|
22
23
|
#
|
23
24
|
# @return MethodDefinitions
|
24
|
-
def add(
|
25
|
-
|
25
|
+
def add(name, code = nil, **options, &block)
|
26
|
+
definitions << MethodDefinition.from(name, code, **options, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# @private
|
32
|
+
#
|
33
|
+
# All definitions
|
34
|
+
#
|
35
|
+
# @return [Array<MethodDefinition>]
|
36
|
+
def definitions
|
37
|
+
@definitions ||= []
|
26
38
|
end
|
27
39
|
end
|
28
40
|
end
|
data/lib/sinclair/version.rb
CHANGED
data/sinclair.gemspec
CHANGED
@@ -35,6 +35,6 @@ Gem::Specification.new do |gem|
|
|
35
35
|
gem.add_development_dependency 'rubocop-rspec', '1.33.0'
|
36
36
|
gem.add_development_dependency 'rubycritic', '4.1.0'
|
37
37
|
gem.add_development_dependency 'simplecov', '0.17.0'
|
38
|
-
gem.add_development_dependency 'yard', '0.9.
|
38
|
+
gem.add_development_dependency 'yard', '0.9.20'
|
39
39
|
gem.add_development_dependency 'yardstick', '0.9.9'
|
40
40
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::MethodBuilder::BlockMethodBuilder do
|
6
|
+
describe '#build' do
|
7
|
+
subject(:builder) do
|
8
|
+
described_class.new(klass, definition, type: type)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:klass) { Class.new }
|
12
|
+
let(:instance) { klass.new }
|
13
|
+
let(:value) { Random.rand }
|
14
|
+
let(:method_name) { :the_method }
|
15
|
+
|
16
|
+
let(:definition) do
|
17
|
+
result = value
|
18
|
+
Sinclair::MethodDefinition.from(method_name) { result }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when type is instance' do
|
22
|
+
let(:type) { Sinclair::MethodBuilder::INSTANCE_METHOD }
|
23
|
+
|
24
|
+
it do
|
25
|
+
expect { builder.build }
|
26
|
+
.to add_method(method_name).to(instance)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when the method is built' do
|
30
|
+
before { builder.build }
|
31
|
+
|
32
|
+
it 'returns the result of the block when called' do
|
33
|
+
expect(instance.the_method).to eq(value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when type is class' do
|
39
|
+
let(:type) { Sinclair::MethodBuilder::CLASS_METHOD }
|
40
|
+
|
41
|
+
it do
|
42
|
+
expect { builder.build }
|
43
|
+
.to add_class_method(method_name).to(klass)
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when the method is built' do
|
47
|
+
before { builder.build }
|
48
|
+
|
49
|
+
it 'returns the result of the block when called' do
|
50
|
+
expect(klass.the_method).to eq(value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::MethodBuilder::StringMethodBuilder do
|
6
|
+
describe '#build' do
|
7
|
+
subject(:builder) do
|
8
|
+
described_class.new(klass, definition, type: type)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:klass) { Class.new }
|
12
|
+
let(:instance) { klass.new }
|
13
|
+
let(:value) { Random.rand }
|
14
|
+
let(:method_name) { :the_method }
|
15
|
+
|
16
|
+
let(:definition) do
|
17
|
+
Sinclair::MethodDefinition.from(method_name, value.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when type is instance' do
|
21
|
+
let(:type) { Sinclair::MethodBuilder::INSTANCE_METHOD }
|
22
|
+
|
23
|
+
it do
|
24
|
+
expect { builder.build }
|
25
|
+
.to add_method(method_name).to(instance)
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when the method is built' do
|
29
|
+
before { builder.build }
|
30
|
+
|
31
|
+
it 'returns the result of the code when called' do
|
32
|
+
expect(instance.the_method).to eq(value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when type is class' do
|
38
|
+
let(:type) { Sinclair::MethodBuilder::CLASS_METHOD }
|
39
|
+
|
40
|
+
it do
|
41
|
+
expect { builder.build }
|
42
|
+
.to add_class_method(method_name).to(klass)
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when the method is built' do
|
46
|
+
before { builder.build }
|
47
|
+
|
48
|
+
it 'returns the result of the code when called' do
|
49
|
+
expect(klass.the_method).to eq(value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::MethodBuilder do
|
6
|
+
subject(:builder) { described_class.new(klass) }
|
7
|
+
|
8
|
+
let(:klass) { Class.new }
|
9
|
+
let(:definitions) { Sinclair::MethodDefinitions.new }
|
10
|
+
let(:value) { Random.rand }
|
11
|
+
let(:method_name) { :the_method }
|
12
|
+
let(:instance) { klass.new }
|
13
|
+
|
14
|
+
before do
|
15
|
+
definitions.add(method_name, value.to_s)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#build_methods' do
|
19
|
+
context 'when building an instance method' do
|
20
|
+
let(:type) { described_class::INSTANCE_METHOD }
|
21
|
+
|
22
|
+
it do
|
23
|
+
expect { builder.build_methods(definitions, type) }
|
24
|
+
.to add_method(method_name).to(instance)
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when the method is called' do
|
28
|
+
before { builder.build_methods(definitions, type) }
|
29
|
+
|
30
|
+
it do
|
31
|
+
expect(instance.the_method).to eq(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when building a class method' do
|
37
|
+
let(:type) { described_class::INSTANCE_METHOD }
|
38
|
+
|
39
|
+
it do
|
40
|
+
expect { builder.build_methods(definitions, type) }
|
41
|
+
.to add_method(method_name).to(instance)
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when the method is called' do
|
45
|
+
before { builder.build_methods(definitions, type) }
|
46
|
+
|
47
|
+
it do
|
48
|
+
expect(instance.the_method).to eq(value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|