sinclair 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/README.md +414 -324
  4. data/config/check_specs.yml +3 -4
  5. data/config/yardstick.yml +2 -0
  6. data/lib/sinclair/matchers/add_class_method.rb +0 -1
  7. data/lib/sinclair/method_builder/base.rb +17 -2
  8. data/lib/sinclair/method_builder/call_method_builder.rb +21 -21
  9. data/lib/sinclair/method_builder.rb +5 -20
  10. data/lib/sinclair/method_definition/block_definition.rb +2 -0
  11. data/lib/sinclair/method_definition/call_definition.rb +15 -18
  12. data/lib/sinclair/method_definition/string_definition.rb +2 -0
  13. data/lib/sinclair/method_definition.rb +41 -3
  14. data/lib/sinclair/method_definitions.rb +20 -22
  15. data/lib/sinclair/version.rb +1 -1
  16. data/lib/sinclair.rb +149 -62
  17. data/spec/integration/readme/sinclair/types_of_definition_spec.rb +47 -0
  18. data/spec/integration/yard/sinclair/add_class_method_spec.rb +51 -0
  19. data/spec/integration/yard/sinclair/add_method_spec.rb +60 -0
  20. data/spec/integration/yard/sinclair/eval_and_add_method_spec.rb +26 -0
  21. data/spec/integration/yard/sinclair_spec.rb +0 -83
  22. data/spec/lib/sinclair/method_builder/base_spec.rb +15 -0
  23. data/spec/lib/sinclair/method_definition/call_definition_spec.rb +14 -17
  24. data/spec/lib/sinclair/method_definition_spec.rb +67 -2
  25. data/spec/lib/sinclair/method_definitions_spec.rb +15 -16
  26. data/spec/lib/sinclair_spec.rb +6 -160
  27. data/spec/support/models/dummy_builder.rb +4 -1
  28. data/spec/support/models/dummy_class_builder.rb +3 -0
  29. data/spec/support/models/person.rb +1 -1
  30. data/spec/support/shared_examples/sinclair.rb +112 -0
  31. metadata +8 -2
@@ -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 '#code_string' do
14
- let(:expected) { 'method_call :key1, :value2' }
15
-
16
- it 'returns the code string' do
17
- expect(definition.code_string)
18
- .to eq(expected)
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
- describe '#class_code_string' do
23
- let(:expected) do
24
- <<-RUBY
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 code string' do
32
- expect(definition.class_code_string.gsub(/^ */, ''))
33
- .to eq(expected.gsub(/^ */, ''))
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).code_string)
63
- .to eq('attr_reader :some_attribute, :other_attribute')
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) { :the_method }
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.add_definition(type, *arguments))
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.add_definition(type, *arguments).last)
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.add_definition(type, *arguments).last)
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.add_definition(type, *arguments).last.code_string)
68
- .to eq('attr_reader :some_attribute, :other_attribute')
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.add_definition(type, method_name, &block))
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.add_definition(type, method_name, &block).last)
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.add_definition(type, method_name, &block).last)
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.add_definition(type, method_name, &block).last.name)
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.add_definition(type, method_name, code))
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.add_definition(type, method_name, code).last)
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.add_definition(type, method_name, code).last)
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.add_definition(type, method_name, code).last.name)
118
+ expect(definitions.add(method_name, code, type: type).last.name)
120
119
  .to eq(method_name)
121
120
  end
122
121
  end