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.
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