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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/README.md +414 -324
- data/config/check_specs.yml +3 -4
- data/config/yardstick.yml +2 -0
- data/lib/sinclair/matchers/add_class_method.rb +0 -1
- data/lib/sinclair/method_builder/base.rb +17 -2
- data/lib/sinclair/method_builder/call_method_builder.rb +21 -21
- data/lib/sinclair/method_builder.rb +5 -20
- data/lib/sinclair/method_definition/block_definition.rb +2 -0
- data/lib/sinclair/method_definition/call_definition.rb +15 -18
- data/lib/sinclair/method_definition/string_definition.rb +2 -0
- data/lib/sinclair/method_definition.rb +41 -3
- data/lib/sinclair/method_definitions.rb +20 -22
- data/lib/sinclair/version.rb +1 -1
- data/lib/sinclair.rb +149 -62
- data/spec/integration/readme/sinclair/types_of_definition_spec.rb +47 -0
- data/spec/integration/yard/sinclair/add_class_method_spec.rb +51 -0
- data/spec/integration/yard/sinclair/add_method_spec.rb +60 -0
- data/spec/integration/yard/sinclair/eval_and_add_method_spec.rb +26 -0
- data/spec/integration/yard/sinclair_spec.rb +0 -83
- data/spec/lib/sinclair/method_builder/base_spec.rb +15 -0
- data/spec/lib/sinclair/method_definition/call_definition_spec.rb +14 -17
- data/spec/lib/sinclair/method_definition_spec.rb +67 -2
- data/spec/lib/sinclair/method_definitions_spec.rb +15 -16
- data/spec/lib/sinclair_spec.rb +6 -160
- data/spec/support/models/dummy_builder.rb +4 -1
- data/spec/support/models/dummy_class_builder.rb +3 -0
- data/spec/support/models/person.rb +1 -1
- data/spec/support/shared_examples/sinclair.rb +112 -0
- metadata +8 -2
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair do
|
6
|
+
describe 'README' do
|
7
|
+
describe 'Define method using block' do
|
8
|
+
it 'adds the method' do
|
9
|
+
klass = Class.new
|
10
|
+
instance = klass.new
|
11
|
+
|
12
|
+
builder = described_class.new(klass)
|
13
|
+
builder.add_method(:random_number) { Random.rand(10..20) }
|
14
|
+
builder.build
|
15
|
+
|
16
|
+
expect(instance.random_number).to be_between(10, 20)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'Define method using string' do
|
21
|
+
it 'adds the method' do
|
22
|
+
klass = Class.new
|
23
|
+
instance = klass.new
|
24
|
+
|
25
|
+
builder = described_class.new(klass)
|
26
|
+
builder.add_method(:random_number, 'Random.rand(10..20)')
|
27
|
+
builder.build
|
28
|
+
|
29
|
+
expect(instance.random_number).to be_between(10, 20)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'Define method using call to the class' do
|
34
|
+
it 'performs the call to the class' do
|
35
|
+
klass = Class.new
|
36
|
+
|
37
|
+
builder = described_class.new(klass)
|
38
|
+
builder.add_class_method(:attr_accessor, :number, type: :call)
|
39
|
+
builder.build
|
40
|
+
|
41
|
+
expect(klass.number).to be_nil
|
42
|
+
klass.number = 10
|
43
|
+
expect(klass.number).to eq(10)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'yard Sinclair#add_class_method' do
|
6
|
+
let(:klass) { Class.new }
|
7
|
+
|
8
|
+
describe 'Adding a method by String' do
|
9
|
+
it 'returns the hostname' do
|
10
|
+
builder = Sinclair.new(klass)
|
11
|
+
builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
|
12
|
+
builder.build
|
13
|
+
ENV['HOSTNAME'] = 'myhost'
|
14
|
+
|
15
|
+
expect(klass.hostname).to eq('myhost')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'Adding a method by Block' do
|
20
|
+
it 'returns the timeout' do
|
21
|
+
builder = Sinclair.new(klass)
|
22
|
+
builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
|
23
|
+
builder.build
|
24
|
+
ENV['TIMEOUT'] = '300'
|
25
|
+
|
26
|
+
expect(klass.timeout).to eq('300')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'Passing type block' do
|
31
|
+
it 'creates new method' do
|
32
|
+
builder = Sinclair.new(klass)
|
33
|
+
builder.add_class_method(:timeout, type: :block) { ENV['TIMEOUT'] }
|
34
|
+
builder.build
|
35
|
+
ENV['TIMEOUT'] = '300'
|
36
|
+
|
37
|
+
expect(klass.timeout).to eq('300')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'Passing type call' do
|
42
|
+
it 'creates new method' do
|
43
|
+
builder = Sinclair.new(klass)
|
44
|
+
builder.add_class_method(:attr_accessor, :timeout, type: :call)
|
45
|
+
builder.build
|
46
|
+
|
47
|
+
klass.timeout = 10
|
48
|
+
expect(klass.timeout).to eq(10)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'yard Sinclair#add_method' do
|
6
|
+
describe 'Using string code to add a string defined method' do
|
7
|
+
let(:klass) { Class.new(Person) }
|
8
|
+
|
9
|
+
it 'creates new method' do
|
10
|
+
builder = Sinclair.new(klass)
|
11
|
+
builder.add_method(:full_name, '[first_name, last_name].join(" ")')
|
12
|
+
builder.build
|
13
|
+
|
14
|
+
expect(klass.new('john', 'wick').full_name).to eq('john wick')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'Using block to add a block method' do
|
19
|
+
let(:klass) { Class.new(Person) }
|
20
|
+
|
21
|
+
it 'creates new method' do
|
22
|
+
builder = Sinclair.new(klass)
|
23
|
+
builder.add_method(:bond_name) { "#{last_name}, #{first_name} #{last_name}" }
|
24
|
+
builder.build
|
25
|
+
|
26
|
+
expect(klass.new('john', 'wick').bond_name).to eq('wick, john wick')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'Passing type block' do
|
31
|
+
let(:klass) { Class.new(Person) }
|
32
|
+
|
33
|
+
it 'creates new method' do
|
34
|
+
builder = Sinclair.new(klass)
|
35
|
+
builder.add_method(:bond_name, type: :block, cached: true) do
|
36
|
+
"#{last_name}, #{first_name} #{last_name}"
|
37
|
+
end
|
38
|
+
builder.build
|
39
|
+
person = klass.new('john', 'wick')
|
40
|
+
|
41
|
+
expect(person.bond_name).to eq('wick, john wick')
|
42
|
+
person.first_name = 'Johny'
|
43
|
+
expect(person.bond_name).to eq('wick, john wick')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'Passing type call' do
|
48
|
+
let(:klass) { Class.new }
|
49
|
+
|
50
|
+
it 'creates new method' do
|
51
|
+
builder = Sinclair.new(klass)
|
52
|
+
builder.add_method(:attr_accessor, :bond_name, type: :call)
|
53
|
+
builder.build
|
54
|
+
person = klass.new
|
55
|
+
|
56
|
+
person.bond_name = 'Bond, James Bond'
|
57
|
+
expect(person.bond_name).to eq('Bond, James Bond')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'yard Sinclair#eval_and_add_method' do
|
6
|
+
describe 'Building a initial value class method' do
|
7
|
+
let(:klass) do
|
8
|
+
Class.new do
|
9
|
+
include InitialValuer
|
10
|
+
attr_writer :age
|
11
|
+
|
12
|
+
initial_value_for :age, 20
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when it has not been initialized' do
|
17
|
+
it do
|
18
|
+
object = klass.new
|
19
|
+
|
20
|
+
expect(object.age).to eq(20)
|
21
|
+
object.age = 30
|
22
|
+
expect(object.age).to eq(30)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -119,88 +119,5 @@ describe Sinclair do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
123
|
-
describe '#add_method' do
|
124
|
-
let(:klass) { Class.new(Person) }
|
125
|
-
let(:instance) { klass.new('john', 'wick') }
|
126
|
-
|
127
|
-
before do
|
128
|
-
builder.add_method(:full_name, '[first_name, last_name].join(" ")')
|
129
|
-
builder.add_method(:bond_name) { "#{last_name}, #{first_name} #{last_name}" }
|
130
|
-
builder.build
|
131
|
-
end
|
132
|
-
|
133
|
-
describe '#full_name' do
|
134
|
-
it 'returns the full name' do
|
135
|
-
expect(instance.full_name).to eq('john wick')
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe '#bond_name' do
|
140
|
-
it 'returns the full name, bond style' do
|
141
|
-
expect(instance.bond_name).to eq('wick, john wick')
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
describe '#add_class_method' do
|
147
|
-
let(:klass) { env_fetcher }
|
148
|
-
let(:env_fetcher) { Class.new }
|
149
|
-
|
150
|
-
describe '#hostname' do
|
151
|
-
before do
|
152
|
-
builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
|
153
|
-
builder.build
|
154
|
-
ENV['HOSTNAME'] = 'myhost'
|
155
|
-
end
|
156
|
-
|
157
|
-
it 'returns the hostname' do
|
158
|
-
expect(env_fetcher.hostname).to eq('myhost')
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
describe '#timeout' do
|
163
|
-
before do
|
164
|
-
builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
|
165
|
-
builder.build
|
166
|
-
ENV['TIMEOUT'] = '300'
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'returns the timeout' do
|
170
|
-
expect(env_fetcher.timeout).to eq('300')
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe '#eval_and_add_method' do
|
176
|
-
subject(:builder) { klass.new }
|
177
|
-
|
178
|
-
let(:klass) do
|
179
|
-
Class.new do
|
180
|
-
include InitialValuer
|
181
|
-
attr_writer :age
|
182
|
-
initial_value_for :age, 20
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe '#age' do
|
187
|
-
context 'when it has not been initialized' do
|
188
|
-
it do
|
189
|
-
expect(builder.age).to eq(20)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
context 'when it has been initialized' do
|
194
|
-
before do
|
195
|
-
builder.age
|
196
|
-
builder.age = 30
|
197
|
-
end
|
198
|
-
|
199
|
-
it do
|
200
|
-
expect(builder.age).to eq(30)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
122
|
end
|
206
123
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::MethodBuilder::Base do
|
6
|
+
describe '.build' do
|
7
|
+
let(:klass) { Class.new }
|
8
|
+
let(:type) { Sinclair::MethodBuilder::CLASS_METHOD }
|
9
|
+
|
10
|
+
it do
|
11
|
+
expect { described_class.build(klass, instance_of(described_class), type: type) }
|
12
|
+
.to raise_error(NotImplementedError)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -10,27 +10,24 @@ describe Sinclair::MethodDefinition::CallDefinition do
|
|
10
10
|
let(:call_name) { :method_call }
|
11
11
|
let(:attributes) { %i[key1 value2] }
|
12
12
|
|
13
|
-
describe '#
|
14
|
-
let(:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
describe '#code_block' do
|
14
|
+
let(:instance) { klass.new }
|
15
|
+
let(:klass) do
|
16
|
+
Class.new do
|
17
|
+
def method_call(*args)
|
18
|
+
args
|
19
|
+
end
|
20
|
+
end
|
19
21
|
end
|
20
|
-
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
class << self
|
26
|
-
method_call :key1, :value2
|
27
|
-
end
|
28
|
-
RUBY
|
23
|
+
it do
|
24
|
+
expect(definition.code_block)
|
25
|
+
.to be_a(Proc)
|
29
26
|
end
|
30
27
|
|
31
|
-
it 'returns the
|
32
|
-
expect(definition.
|
33
|
-
.to eq(
|
28
|
+
it 'returns a proc with the method call' do
|
29
|
+
expect(instance.instance_eval(&definition.code_block))
|
30
|
+
.to eq(attributes)
|
34
31
|
end
|
35
32
|
end
|
36
33
|
end
|
@@ -5,6 +5,48 @@ require 'spec_helper'
|
|
5
5
|
describe Sinclair::MethodDefinition do
|
6
6
|
let(:method_name) { :the_method }
|
7
7
|
|
8
|
+
describe '.build' do
|
9
|
+
subject(:definition) do
|
10
|
+
definition_class.new(method_name, **options)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:definition_class) { Class.new(described_class) }
|
14
|
+
let(:options) { {} }
|
15
|
+
let(:klass) { Class.new }
|
16
|
+
let(:type) { Sinclair::MethodBuilder::CLASS_METHOD }
|
17
|
+
|
18
|
+
context 'when the builder has not been defined' do
|
19
|
+
it do
|
20
|
+
expect { definition.build(klass, type) }
|
21
|
+
.to raise_error(NotImplementedError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when the builder has been defined' do
|
26
|
+
let(:definition_class) do
|
27
|
+
Class.new(described_class) do
|
28
|
+
def code_line
|
29
|
+
'10'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
before do
|
35
|
+
definition_class.build_with(Sinclair::MethodBuilder::StringMethodBuilder)
|
36
|
+
end
|
37
|
+
|
38
|
+
it do
|
39
|
+
expect { definition.build(klass, type) }
|
40
|
+
.not_to raise_error
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'builds the method using the builder' do
|
44
|
+
expect { definition.build(klass, type) }
|
45
|
+
.to add_class_method(method_name).to(klass)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
8
50
|
describe '.default_value' do
|
9
51
|
subject(:klass) { Class.new(described_class) }
|
10
52
|
|
@@ -44,6 +86,8 @@ describe Sinclair::MethodDefinition do
|
|
44
86
|
end
|
45
87
|
|
46
88
|
describe '.for' do
|
89
|
+
let(:klass) { Class.new }
|
90
|
+
|
47
91
|
context 'when there are no options nor block' do
|
48
92
|
let(:type) { :call }
|
49
93
|
let(:arguments) { %i[attr_reader some_attribute other_attribute] }
|
@@ -59,8 +103,29 @@ describe Sinclair::MethodDefinition do
|
|
59
103
|
end
|
60
104
|
|
61
105
|
it 'initializes it correctly' do
|
62
|
-
expect(described_class.for(type, *arguments).
|
63
|
-
.to
|
106
|
+
expect { klass.module_eval(&described_class.for(type, *arguments).code_block) }
|
107
|
+
.to add_method(:some_attribute).to(klass)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when type is not given' do
|
112
|
+
let(:type) { nil }
|
113
|
+
let(:method_name) { :the_method }
|
114
|
+
let(:block) { proc { 10 } }
|
115
|
+
|
116
|
+
it do
|
117
|
+
expect(described_class.for(type, method_name, &block))
|
118
|
+
.to be_a(described_class)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'infers the definition from arguments' do
|
122
|
+
expect(described_class.for(type, method_name, &block))
|
123
|
+
.to be_a(described_class::BlockDefinition)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'initializes it correctly' do
|
127
|
+
expect(described_class.for(type, method_name, &block).name)
|
128
|
+
.to eq(method_name)
|
64
129
|
end
|
65
130
|
end
|
66
131
|
|
@@ -6,7 +6,8 @@ describe Sinclair::MethodDefinitions do
|
|
6
6
|
subject(:definitions) { described_class.new }
|
7
7
|
|
8
8
|
describe '#add' do
|
9
|
-
let(:name)
|
9
|
+
let(:name) { :the_method }
|
10
|
+
let(:klass) { Class.new }
|
10
11
|
|
11
12
|
context 'when passing block' do
|
12
13
|
it 'returns the resulting array' do
|
@@ -41,31 +42,29 @@ describe Sinclair::MethodDefinitions do
|
|
41
42
|
.to be_a(Sinclair::MethodDefinition::StringDefinition)
|
42
43
|
end
|
43
44
|
end
|
44
|
-
end
|
45
45
|
|
46
|
-
describe '#add_definition' do
|
47
46
|
context 'when there are no options nor block' do
|
48
47
|
let(:type) { :call }
|
49
48
|
let(:arguments) { %i[attr_reader some_attribute other_attribute] }
|
50
49
|
|
51
50
|
it do
|
52
|
-
expect(definitions.
|
51
|
+
expect(definitions.add(*arguments, type: type))
|
53
52
|
.to be_a(Array)
|
54
53
|
end
|
55
54
|
|
56
55
|
it 'creates a new definition' do
|
57
|
-
expect(definitions.
|
56
|
+
expect(definitions.add(*arguments, type: type).last)
|
58
57
|
.to be_a(Sinclair::MethodDefinition)
|
59
58
|
end
|
60
59
|
|
61
60
|
it 'creates a new definition of the chosen type' do
|
62
|
-
expect(definitions.
|
61
|
+
expect(definitions.add(*arguments, type: type).last)
|
63
62
|
.to be_a(Sinclair::MethodDefinition::CallDefinition)
|
64
63
|
end
|
65
64
|
|
66
65
|
it 'initializes it correctly' do
|
67
|
-
expect(definitions.
|
68
|
-
.to
|
66
|
+
expect { klass.module_eval(&definitions.add(*arguments, type: type).last.code_block) }
|
67
|
+
.to add_method(:some_attribute).to(klass)
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
@@ -75,22 +74,22 @@ describe Sinclair::MethodDefinitions do
|
|
75
74
|
let(:block) { proc { 10 } }
|
76
75
|
|
77
76
|
it do
|
78
|
-
expect(definitions.
|
77
|
+
expect(definitions.add(type, method_name, &block))
|
79
78
|
.to be_a(Array)
|
80
79
|
end
|
81
80
|
|
82
81
|
it 'creates a new definition' do
|
83
|
-
expect(definitions.
|
82
|
+
expect(definitions.add(type, method_name, &block).last)
|
84
83
|
.to be_a(Sinclair::MethodDefinition)
|
85
84
|
end
|
86
85
|
|
87
86
|
it 'creates a new definition of the chosen type' do
|
88
|
-
expect(definitions.
|
87
|
+
expect(definitions.add(type, method_name, &block).last)
|
89
88
|
.to be_a(Sinclair::MethodDefinition::BlockDefinition)
|
90
89
|
end
|
91
90
|
|
92
91
|
it 'initializes it correctly' do
|
93
|
-
expect(definitions.
|
92
|
+
expect(definitions.add(method_name, type: type, &block).last.name)
|
94
93
|
.to eq(method_name)
|
95
94
|
end
|
96
95
|
end
|
@@ -101,22 +100,22 @@ describe Sinclair::MethodDefinitions do
|
|
101
100
|
let(:code) { '10' }
|
102
101
|
|
103
102
|
it do
|
104
|
-
expect(definitions.
|
103
|
+
expect(definitions.add(method_name, code, type: type))
|
105
104
|
.to be_a(Array)
|
106
105
|
end
|
107
106
|
|
108
107
|
it 'creates a new definition' do
|
109
|
-
expect(definitions.
|
108
|
+
expect(definitions.add(method_name, code, type: type).last)
|
110
109
|
.to be_a(Sinclair::MethodDefinition)
|
111
110
|
end
|
112
111
|
|
113
112
|
it 'creates a new definition of the chosen type' do
|
114
|
-
expect(definitions.
|
113
|
+
expect(definitions.add(method_name, code, type: type).last)
|
115
114
|
.to be_a(Sinclair::MethodDefinition::StringDefinition)
|
116
115
|
end
|
117
116
|
|
118
117
|
it 'initializes it correctly' do
|
119
|
-
expect(definitions.
|
118
|
+
expect(definitions.add(method_name, code, type: type).last.name)
|
120
119
|
.to eq(method_name)
|
121
120
|
end
|
122
121
|
end
|