sinclair 1.4.1 → 1.4.2

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +5 -3
  3. data/.rubocop.yml +20 -4
  4. data/Dockerfile +8 -4
  5. data/README.md +1 -1
  6. data/config/yardstick.yml +10 -35
  7. data/lib/sinclair.rb +87 -18
  8. data/lib/sinclair/config.rb +3 -0
  9. data/lib/sinclair/config/methods_builder.rb +15 -1
  10. data/lib/sinclair/config_builder.rb +1 -0
  11. data/lib/sinclair/config_class.rb +1 -0
  12. data/lib/sinclair/config_factory.rb +15 -0
  13. data/lib/sinclair/configurable.rb +1 -0
  14. data/lib/sinclair/matchers.rb +20 -6
  15. data/lib/sinclair/matchers/add_class_method.rb +56 -0
  16. data/lib/sinclair/matchers/add_class_method_to.rb +98 -0
  17. data/lib/sinclair/matchers/add_instance_method.rb +85 -0
  18. data/lib/sinclair/matchers/add_instance_method_to.rb +119 -0
  19. data/lib/sinclair/matchers/add_method.rb +11 -73
  20. data/lib/sinclair/matchers/add_method_to.rb +13 -111
  21. data/lib/sinclair/method_definition.rb +18 -58
  22. data/lib/sinclair/method_definition/block_definition.rb +37 -6
  23. data/lib/sinclair/method_definition/class_block_definition.rb +22 -0
  24. data/lib/sinclair/method_definition/class_method_definition.rb +50 -0
  25. data/lib/sinclair/method_definition/class_string_definition.rb +24 -0
  26. data/lib/sinclair/method_definition/instance_block_definition.rb +22 -0
  27. data/lib/sinclair/method_definition/instance_method_definition.rb +48 -0
  28. data/lib/sinclair/method_definition/instance_string_definition.rb +24 -0
  29. data/lib/sinclair/method_definition/string_definition.rb +39 -5
  30. data/lib/sinclair/method_definitions.rb +28 -0
  31. data/lib/sinclair/options_parser.rb +5 -0
  32. data/lib/sinclair/version.rb +1 -1
  33. data/sinclair.gemspec +16 -10
  34. data/spec/integration/yard/sinclair/matchers/add_class_method_spec.rb +23 -0
  35. data/spec/integration/yard/sinclair/matchers/add_class_method_to_spec.rb +19 -0
  36. data/spec/integration/yard/sinclair/matchers/{add_method_spec.rb → add_instance_method_spec.rb} +3 -3
  37. data/spec/integration/yard/sinclair/matchers/{add_method_to_spec.rb → add_instance_method_to_spec.rb} +1 -1
  38. data/spec/integration/yard/sinclair/method_definition/class_block_definition_spec.rb +34 -0
  39. data/spec/integration/yard/sinclair/method_definition/class_method_definition_spec.rb +28 -0
  40. data/spec/integration/yard/sinclair/method_definition/class_string_definition_spec.rb +23 -0
  41. data/spec/integration/yard/sinclair/method_definition/{block_definition_spec.rb → instance_block_definition_spec.rb} +2 -2
  42. data/spec/integration/yard/sinclair/method_definition/instance_method_definition_spec.rb +35 -0
  43. data/spec/integration/yard/sinclair/method_definition/{string_definition_spec.rb → instance_string_definition_spec.rb} +1 -1
  44. data/spec/integration/yard/sinclair_spec.rb +32 -5
  45. data/spec/lib/sinclair/matchers/add_class_method_spec.rb +36 -0
  46. data/spec/lib/sinclair/matchers/add_class_method_to_spec.rb +77 -0
  47. data/spec/lib/sinclair/matchers/{add_method_spec.rb → add_instance_method_spec.rb} +11 -4
  48. data/spec/lib/sinclair/matchers/{add_method_to_spec.rb → add_instance_method_to_spec.rb} +2 -2
  49. data/spec/lib/sinclair/matchers_spec.rb +17 -2
  50. data/spec/lib/sinclair/method_definition/class_block_definition_spec.rb +29 -0
  51. data/spec/lib/sinclair/method_definition/class_string_definition_spec.rb +27 -0
  52. data/spec/lib/sinclair/method_definition/{block_definition_spec.rb → instance_block_definition_spec.rb} +2 -2
  53. data/spec/lib/sinclair/method_definition/{string_definition_spec.rb → instance_string_definition_spec.rb} +2 -2
  54. data/spec/lib/sinclair/method_definition_spec.rb +52 -6
  55. data/spec/lib/sinclair_spec.rb +83 -0
  56. data/spec/support/models/dummy_class_builder.rb +11 -0
  57. data/spec/support/shared_examples/class_method_definition.rb +96 -0
  58. data/spec/support/shared_examples/{method_definition.rb → instance_method_definition.rb} +0 -0
  59. metadata +148 -45
  60. data/scripts/check_readme.sh +0 -6
  61. data/scripts/rubycritic.sh +0 -10
  62. data/spec/integration/sinclair/matchers_spec.rb +0 -99
  63. data/spec/integration/yard/sinclair/method_definition_spec.rb +0 -56
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ class MethodDefinition
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # Define a method from block
9
+ class InstanceBlockDefinition < BlockDefinition
10
+ private
11
+
12
+ # @private
13
+ #
14
+ # Method used to define an instance method
15
+ #
16
+ # @return [Symbol] Always :define_method
17
+ def method_definer
18
+ :define_method
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ class MethodDefinition
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # Module responsible for building instance method definitions
9
+ module InstanceMethodDefinition
10
+ # Returns an instance method definition
11
+ #
12
+ # When block is given returns an instance of
13
+ # {InstanceBlockDefinition}, and when not, returns
14
+ # {InstanceStringDefinition}
15
+ #
16
+ # @param name [String,Symbol] name of the method
17
+ # @param code [String] code to be evaluated as method
18
+ # @param block [Proc] block with code to be added as method
19
+ # @param options [Hash] Options of construction
20
+ # @option options cached [Boolean] Flag telling to create
21
+ # a method with cache
22
+ #
23
+ # @example
24
+ # klass = Class.new
25
+ #
26
+ # method_definition = Sinclair::MethodDefinition::InstanceMethodDefinition.from(
27
+ # :sequence, '@x = @x.to_i ** 2 + 1'
28
+ # )
29
+ #
30
+ # method_definition.build(klass)
31
+ #
32
+ # instance = klass.new
33
+ #
34
+ # instance.sequence # returns 1
35
+ # instance.sequence # returns 2
36
+ # instance.sequence # returns 5
37
+ #
38
+ # @return MethodDefinition
39
+ def self.from(name, code = nil, **options, &block)
40
+ if block
41
+ InstanceBlockDefinition.new(name, **options, &block)
42
+ else
43
+ InstanceStringDefinition.new(name, code, **options)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ class MethodDefinition
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # Define an instance method from string
9
+ class InstanceStringDefinition < StringDefinition
10
+ private
11
+
12
+ # @private
13
+ #
14
+ # String used when defining method
15
+ #
16
+ # Instance definition always returns +name+
17
+ #
18
+ # @return [String]
19
+ def method_name
20
+ name
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,7 +2,12 @@
2
2
 
3
3
  class Sinclair
4
4
  class MethodDefinition
5
- # Define a method from string
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # @abstract
9
+ #
10
+ # Define an instance method from string
6
11
  class StringDefinition < MethodDefinition
7
12
  # @param name [String,Symbol] name of the method
8
13
  # @param code [String] code to be evaluated as method
@@ -22,17 +27,17 @@ class Sinclair
22
27
  #
23
28
  # @return [Symbol] name of the created method
24
29
  #
25
- # @example With no options
30
+ # @example Using instance string method with no options
26
31
  # class MyModel
27
32
  # end
28
33
  #
29
34
  # instance = MyModel.new
30
35
  #
31
- # method_definition = Sinclair::MethodDefinition.from(
36
+ # method_definition = Sinclair::MethodDefinition::InstanceStringDefinition.new(
32
37
  # :sequence, '@x = @x.to_i ** 2 + 1'
33
38
  # )
34
39
  #
35
- # method_definition.build(klass) # adds instance_method :sequence to
40
+ # method_definition.build(MyModel) # adds instance_method :sequence to
36
41
  # # MyModel instances
37
42
  #
38
43
  # instance.instance_variable_get(:@x) # returns nil
@@ -43,12 +48,41 @@ class Sinclair
43
48
  #
44
49
  # instance.instance_variable_get(:@x) # returns 5
45
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)
69
+ #
70
+ # MyModel.instance_variable_get(:@sequence) # returns 1
71
+ # MyModel.instance_variable_get(:@x) # returns 1
46
72
  def build(klass)
47
73
  klass.module_eval(code_definition, __FILE__, __LINE__ + 1)
48
74
  end
49
75
 
50
76
  private
51
77
 
78
+ # @method code
79
+ # @private
80
+ #
81
+ # Code to be evaluated as method
82
+ #
83
+ # @return [String]
84
+ attr_reader :code
85
+
52
86
  # @private
53
87
  #
54
88
  # Builds full code of method
@@ -58,7 +92,7 @@ class Sinclair
58
92
  code_line = cached? ? code_with_cache : code
59
93
 
60
94
  <<-CODE
61
- def #{name}
95
+ def #{method_name}
62
96
  #{code_line}
63
97
  end
64
98
  CODE
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ # @api private
5
+ # @author darthjee
6
+ #
7
+ # Enumerator holding all method definitions
8
+ class MethodDefinitions < Array
9
+ # Builds and adds new definition
10
+ #
11
+ # @param definition_class [Class] class used to define method definition
12
+ # @param name [String,Symbol] method name
13
+ # @param options [Hash] Options of construction
14
+ # @option options cached [Boolean] Flag telling to create
15
+ # a method with cache
16
+ #
17
+ # @overload add(definition_class, name, code = nil, **options)
18
+ # @param code [String] code to be evaluated when the method is ran
19
+ #
20
+ # @overload add(definition_class, name, **options, &block)
21
+ # @param block [Proc] block to be ran as method
22
+ #
23
+ # @return MethodDefinitions
24
+ def add(definition_class, name, code = nil, **options, &block)
25
+ self << definition_class.from(name, code, **options, &block)
26
+ end
27
+ end
28
+ end
@@ -33,9 +33,14 @@ class Sinclair
33
33
  private
34
34
 
35
35
  # @!visibility public
36
+ #
37
+ # Options hash
38
+ #
39
+ # @return [Hash]
36
40
  attr_reader :options
37
41
 
38
42
  # @!visibility public
43
+ # @api public
39
44
  #
40
45
  # Builds an openstruct of the Hash
41
46
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '1.4.1'
4
+ VERSION = '1.4.2'
5
5
  end
@@ -21,14 +21,20 @@ Gem::Specification.new do |gem|
21
21
 
22
22
  gem.add_runtime_dependency 'activesupport', '~> 5.2.0'
23
23
 
24
- gem.add_development_dependency 'bundler', '~> 1.16.1'
25
- gem.add_development_dependency 'pry-nav', '~> 0.2.4'
26
- gem.add_development_dependency 'rake', '>= 12.3.1'
27
- gem.add_development_dependency 'rspec', '>= 3.8'
28
- gem.add_development_dependency 'rubocop', '0.58.1'
29
- gem.add_development_dependency 'rubocop-rspec', '1.30.0'
30
- gem.add_development_dependency 'rubycritic', '>= 4.0.2'
31
- gem.add_development_dependency 'simplecov', '~> 0.16.x'
32
- gem.add_development_dependency 'yard', '>= 0.9.18'
33
- gem.add_development_dependency 'yardstick', '>= 0.9.9'
24
+ gem.add_development_dependency 'bundler', '~> 1.16.1'
25
+ gem.add_development_dependency 'pry', '0.12.2'
26
+ gem.add_development_dependency 'pry-nav', '0.3.0'
27
+ gem.add_development_dependency 'rake', '12.3.3'
28
+ gem.add_development_dependency 'reek', '5.4.0'
29
+ gem.add_development_dependency 'rspec', '3.8.0'
30
+ gem.add_development_dependency 'rspec-core', '3.8.0'
31
+ gem.add_development_dependency 'rspec-expectations', '3.8.3'
32
+ gem.add_development_dependency 'rspec-mocks', '3.8.0'
33
+ gem.add_development_dependency 'rspec-support', '3.8.0'
34
+ gem.add_development_dependency 'rubocop', '0.73.0'
35
+ gem.add_development_dependency 'rubocop-rspec', '1.33.0'
36
+ gem.add_development_dependency 'rubycritic', '4.1.0'
37
+ gem.add_development_dependency 'simplecov', '0.17.0'
38
+ gem.add_development_dependency 'yard', '0.9.19'
39
+ gem.add_development_dependency 'yardstick', '0.9.9'
34
40
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Sinclair::Matchers::AddClassMethod do
6
+ describe 'yard' do
7
+ describe '#to' do
8
+ context 'when checking against Class' do
9
+ let(:clazz) { Class.new(MyModel) }
10
+
11
+ let(:block) do
12
+ proc do
13
+ clazz.define_singleton_method(:new_method) { 2 }
14
+ end
15
+ end
16
+
17
+ it do
18
+ expect(&block).to add_class_method(:new_method).to(clazz)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::Matchers::AddClassMethodTo do
6
+ describe 'yard' do
7
+ let(:klass) { Class.new(MyModel) }
8
+
9
+ let(:block) do
10
+ proc do
11
+ klass.define_singleton_method(:parent_name) { superclass.name }
12
+ end
13
+ end
14
+
15
+ it do
16
+ expect(&block).to add_class_method(:parent_name).to(klass)
17
+ end
18
+ end
19
+ end
@@ -2,11 +2,11 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe Sinclair::Matchers::AddMethod do
5
+ RSpec.describe Sinclair::Matchers::AddInstanceMethod do
6
6
  describe 'yard' do
7
7
  describe '#to' do
8
8
  context 'when checking against Class' do
9
- let(:clazz) { Class.new }
9
+ let(:clazz) { Class.new(MyModel) }
10
10
  let(:builder) { Sinclair.new(clazz) }
11
11
 
12
12
  before do
@@ -19,7 +19,7 @@ RSpec.describe Sinclair::Matchers::AddMethod do
19
19
  end
20
20
 
21
21
  context 'when checking against instance' do
22
- let(:clazz) { Class.new }
22
+ let(:clazz) { Class.new(MyModel) }
23
23
  let(:builder) { Sinclair.new(clazz) }
24
24
  let(:instance) { clazz.new }
25
25
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Sinclair::Matchers::AddMethodTo do
5
+ describe Sinclair::Matchers::AddInstanceMethodTo do
6
6
  describe 'yard' do
7
7
  let(:klass) { Class.new(MyModel) }
8
8
  let(:builder) { Sinclair.new(klass) }
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::MethodDefinition::ClassBlockDefinition do
6
+ describe 'yard' do
7
+ describe '#build' do
8
+ subject(:method_definition) do
9
+ described_class.new(name) do
10
+ @x = @x.to_i**2 + 1
11
+ end
12
+ end
13
+
14
+ let(:klass) { Class.new }
15
+ let(:name) { :sequence }
16
+
17
+ it 'adds a dynamic method' do
18
+ expect { method_definition.build(klass) }.to add_class_method(name).to(klass)
19
+ expect { klass.sequence }
20
+ .to change { klass.instance_variable_get(:@x) }.from(nil).to 1
21
+ expect(klass.sequence).to eq(2)
22
+ expect(klass.sequence).to eq(5)
23
+ end
24
+
25
+ it 'changes instance variable' do
26
+ method_definition.build(klass)
27
+
28
+ expect { klass.sequence }
29
+ .to change { klass.instance_variable_get(:@x) }
30
+ .from(nil).to 1
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::MethodDefinition::ClassMethodDefinition do
6
+ describe 'yard' do
7
+ describe '#build' do
8
+ describe 'using block with cache option' do
9
+ subject(:method_definition) do
10
+ described_class.from(name, cached: true) do
11
+ @x = @x.to_i**2 + 1
12
+ end
13
+ end
14
+
15
+ let(:klass) { Class.new }
16
+ let(:name) { :sequence }
17
+
18
+ it 'adds a dynamic method' do
19
+ expect { method_definition.build(klass) }.to add_class_method(name).to(klass)
20
+ expect { klass.sequence }
21
+ .to change { klass.instance_variable_get(:@x) }.from(nil).to 1
22
+ expect { klass.sequence }.not_to change(klass, :sequence)
23
+ expect(klass.instance_variable_get(:@sequence)).to eq(1)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Sinclair::MethodDefinition::ClassStringDefinition do
4
+ describe 'yard' do
5
+ describe '#build' do
6
+ subject(:method_definition) do
7
+ described_class.new(name, code, cached: true)
8
+ end
9
+
10
+ let(:klass) { Class.new }
11
+ let(:code) { '@x = @x.to_i ** 2 + 1' }
12
+ let(:name) { :sequence }
13
+
14
+ it 'adds a dynamic method' do
15
+ expect { method_definition.build(klass) }.to add_class_method(name).to(klass)
16
+ expect { klass.sequence }
17
+ .to change { klass.instance_variable_get(:@x) }.from(nil).to(1)
18
+ expect { klass.sequence }.not_to change(klass, :sequence)
19
+ expect(klass.instance_variable_get(:@sequence)).to eq(1)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Sinclair::MethodDefinition::BlockDefinition do
3
+ describe Sinclair::MethodDefinition::InstanceBlockDefinition do
4
4
  describe 'yard' do
5
5
  describe '#build' do
6
6
  subject(:method_definition) do
7
- described_class.from(name, cached: true) do
7
+ described_class.new(name, cached: true) do
8
8
  @x = @x.to_i**2 + 1
9
9
  end
10
10
  end