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
@@ -4,92 +4,21 @@ class Sinclair
4
4
  module Matchers
5
5
  # @api private
6
6
  # @author darthjee
7
+ # @abstract
7
8
  #
8
- # AddMethodTo checks whether a method was or not added by the call of a block
9
- #
10
- # This is used with a RSpec DSL method add_method(method_name).to(class_object)
11
- #
12
- # @author darthjee
13
- #
14
- # @example
15
- # RSpec.configure do |config|
16
- # config.include Sinclair::Matchers
17
- # end
18
- #
19
- # class MyModel
20
- # end
21
- #
22
- # RSpec.describe 'my test' do
23
- # let(:klass) { Class.new(MyModel) }
24
- # let(:builder) { Sinclair.new(klass) }
25
- #
26
- # before do
27
- # builder.add_method(:class_name, 'self.class.name')
28
- # end
29
- #
30
- # it do
31
- # expect { builder.build }.to add_method(:class_name).to(klass)
32
- # end
33
- # end
9
+ # Base class for add_method_to matcher
34
10
  class AddMethodTo < RSpec::Matchers::BuiltIn::BaseMatcher
35
- # @private
36
- #
37
- # Returns a new instance of AddMethodTo
38
- #
39
- # @overload initialize(klass, method)
40
- # @param [Class] klass
41
- # class where the method should be added to
42
- #
43
- # @overload initialize(instance, method)
44
- # @param [Object] klass
45
- # instance of the class where the method should be added to
46
- #
47
- # @param method
48
- # method name
49
- def initialize(target, method)
50
- if target.is_a?(Class)
51
- @klass = target
52
- else
53
- @instance = target
54
- end
11
+ # @param method [SYmbol,String] method name
12
+ def initialize(method)
55
13
  @method = method
56
14
  end
57
15
 
58
- # @private
59
- #
60
- # Returnst expectaton description
61
- #
62
- # @return [String]
63
- def description
64
- "add method '#{method}' to #{klass} instances"
65
- end
66
-
67
- # @private
68
- #
69
- # Returns message on expectation failure
70
- #
71
- # @return [String]
72
- def failure_message_for_should
73
- "expected '#{method}' to be added to #{klass} but " \
74
- "#{@initial_state ? 'it already existed' : "it didn't"}"
75
- end
76
-
77
- # @private
78
- #
79
- # Returns message on expectation failure for negative expectation
80
- #
81
- # @return [String]
82
- def failure_message_for_should_not
83
- "expected '#{method}' not to be added to #{klass} but it was"
84
- end
85
-
86
- # @private
87
- #
88
16
  # Checks if expectation is true or not
89
17
  #
90
18
  # @return [Boolean] expectation check
91
19
  def matches?(event_proc)
92
20
  return false unless event_proc.is_a?(Proc)
21
+
93
22
  raise_block_syntax_error if block_given?
94
23
  perform_change(event_proc)
95
24
  added?
@@ -100,26 +29,27 @@ class Sinclair
100
29
  true
101
30
  end
102
31
 
103
- # @api private
104
- #
105
32
  # Checkes if another instnce is equal self
106
33
  #
107
34
  # @return [Boolean]
108
35
  def equal?(other)
109
36
  return unless other.class == self.class
37
+
110
38
  other.method == method &&
111
- other.instance == instance
39
+ other.klass == klass
112
40
  end
113
41
 
114
42
  alias == equal?
115
- alias failure_message failure_message_for_should
116
- alias failure_message_when_negated failure_message_for_should_not
117
43
 
118
44
  protected
119
45
 
120
- # @api private
46
+ # @method method
121
47
  # @private
122
- attr_reader :method, :instance
48
+ #
49
+ # The method, to be checked, name
50
+ #
51
+ # @return [Symbol]
52
+ attr_reader :method
123
53
 
124
54
  private
125
55
 
@@ -142,34 +72,6 @@ class Sinclair
142
72
  event_proc.call
143
73
  @final_state = method_defined?
144
74
  end
145
-
146
- # @private
147
- #
148
- # Checks if class has instance method defined
149
- #
150
- # @return [Boolean]
151
- def method_defined?
152
- klass.method_defined?(method)
153
- end
154
-
155
- # @private
156
- #
157
- # Class to be analised
158
- #
159
- # @return [Class]
160
- def klass
161
- @klass ||= instance.class
162
- end
163
-
164
- # @private
165
- #
166
- # Raises when block was not given
167
- #
168
- # @raise SyntaxError
169
- def raise_block_syntax_error
170
- raise SyntaxError, 'Block not received by the `add_method_to` matcher. ' \
171
- 'Perhaps you want to use `{ ... }` instead of do/end?'
172
- end
173
75
  end
174
76
  end
175
77
  end
@@ -8,27 +8,20 @@ class Sinclair
8
8
  class MethodDefinition
9
9
  include Sinclair::OptionsParser
10
10
 
11
- autoload :BlockDefinition, 'sinclair/method_definition/block_definition'
12
- autoload :StringDefinition, 'sinclair/method_definition/string_definition'
11
+ autoload :InstanceMethodDefinition, 'sinclair/method_definition/instance_method_definition'
12
+ autoload :ClassMethodDefinition, 'sinclair/method_definition/class_method_definition'
13
+ autoload :BlockDefinition, 'sinclair/method_definition/block_definition'
14
+ autoload :StringDefinition, 'sinclair/method_definition/string_definition'
15
+ autoload :InstanceBlockDefinition, 'sinclair/method_definition/instance_block_definition'
16
+ autoload :InstanceStringDefinition, 'sinclair/method_definition/instance_string_definition'
17
+ autoload :ClassBlockDefinition, 'sinclair/method_definition/class_block_definition'
18
+ autoload :ClassStringDefinition, 'sinclair/method_definition/class_string_definition'
13
19
 
14
20
  # Default options of initialization
15
21
  DEFAULT_OPTIONS = {
16
22
  cached: false
17
23
  }.freeze
18
24
 
19
- # Creates a new instance based on arguments
20
- #
21
- # @return [MethodDefinition] When block is given, a
22
- # new instance of {BlockDefinition} is returned,
23
- # otherwise {StringDefinition} is returned
24
- def self.from(name, code = nil, **options, &block)
25
- if block
26
- BlockDefinition.new(name, **options, &block)
27
- else
28
- StringDefinition.new(name, code, **options)
29
- end
30
- end
31
-
32
25
  # @param name [String,Symbol] name of the method
33
26
  # @param options [Hash] Options of construction
34
27
  # @option options cached [Boolean] Flag telling to create
@@ -38,54 +31,16 @@ class Sinclair
38
31
  @options = DEFAULT_OPTIONS.merge(options)
39
32
  end
40
33
 
34
+ # @abstract
35
+ #
41
36
  # Adds the method to given klass
42
37
  #
43
38
  # This should be implemented on child classes
44
39
  #
45
40
  # @param _klass [Class] class which will receive the new method
46
41
  #
47
- # @example Using block method with no options
48
- # class MyModel
49
- # end
50
- #
51
- # instance = MyModel.new
52
- #
53
- # method_definition = Sinclair::MethodDefinition.from(
54
- # :sequence, '@x = @x.to_i ** 2 + 1'
55
- # )
56
- #
57
- # method_definition.build(klass) # adds instance_method :sequence to
58
- # # MyModel instances
59
- #
60
- # instance.instance_variable_get(:@x) # returns nil
61
- #
62
- # instance.sequence # returns 1
63
- # instance.sequence # returns 2
64
- # instance.sequence # returns 5
65
- #
66
- # instance.instance_variable_get(:@x) # returns 5
67
- #
68
- # @example Using string method with no options
69
- # class MyModel
70
- # end
71
- #
72
- # instance = MyModel.new
73
- #
74
- # method_definition = Sinclair::MethodDefinition.from(:sequence) do
75
- # @x = @x.to_i ** 2 + 1
76
- # end
77
- #
78
- # method_definition.build(klass) # adds instance_method :sequence to
79
- # # MyModel instances
80
- #
81
- # instance.instance_variable_get(:@sequence) # returns nil
82
- # instance.instance_variable_get(:@x) # returns nil
83
- #
84
- # instance.sequence # returns 1
85
- # instance.sequence # returns 1 (cached value)
86
- #
87
- # instance.instance_variable_get(:@sequence) # returns 1
88
- # instance.instance_variable_get(:@x) # returns 1
42
+ # @example (see MethodDefinition::StringDefinition#build)
43
+ # @example (see MethodDefinition::BlockDefinition#build)
89
44
  #
90
45
  # @return [Symbol] name of the created method
91
46
  def build(_klass)
@@ -95,8 +50,13 @@ class Sinclair
95
50
 
96
51
  private
97
52
 
53
+ # @method name
98
54
  # @private
99
- attr_reader :name, :code, :block
55
+ #
56
+ # name of the method
57
+ #
58
+ # @return [String,Symbol]
59
+ attr_reader :name
100
60
  delegate :cached, to: :options_object
101
61
 
102
62
  # @private
@@ -2,6 +2,9 @@
2
2
 
3
3
  class Sinclair
4
4
  class MethodDefinition
5
+ # @abstract
6
+ # @author darthjee
7
+ #
5
8
  # Define a method from block
6
9
  class BlockDefinition < MethodDefinition
7
10
  # @param name [String,Symbol] name of the method
@@ -14,7 +17,7 @@ class Sinclair
14
17
  super(name, **options)
15
18
  end
16
19
 
17
- # Adds the method to given klass
20
+ # Adds the instance method to given klass
18
21
  #
19
22
  # @param klass [Class] class which will receive the new method
20
23
  #
@@ -22,18 +25,20 @@ class Sinclair
22
25
  #
23
26
  # @return [Symbol] name of the created method
24
27
  #
25
- # @example Using block method with no options
28
+ # @example Using instance block method with cached options
26
29
  # class MyModel
27
30
  # end
28
31
  #
29
32
  # instance = MyModel.new
30
33
  #
31
- # method_definition = Sinclair::MethodDefinition::BlockDefinition.new(:sequence) do
34
+ # method_definition = Sinclair::MethodDefinition::InstanceBlockDefinition.new(
35
+ # :sequence, cached: true
36
+ # ) do
32
37
  # @x = @x.to_i ** 2 + 1
33
38
  # end
34
39
  #
35
- # method_definition.build(klass) # adds instance_method :sequence to
36
- # # MyModel instances
40
+ # method_definition.build(MyModel) # adds instance_method :sequence to
41
+ # # MyModel instances
37
42
  #
38
43
  # instance.instance_variable_get(:@sequence) # returns nil
39
44
  # instance.instance_variable_get(:@x) # returns nil
@@ -43,12 +48,38 @@ class Sinclair
43
48
  #
44
49
  # instance.instance_variable_get(:@sequence) # returns 1
45
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
46
70
  def build(klass)
47
- klass.send(:define_method, name, method_block)
71
+ klass.send(method_definer, name, method_block)
48
72
  end
49
73
 
50
74
  private
51
75
 
76
+ # @method block
77
+ # @private
78
+ #
79
+ # Block with code to be added as method
80
+ # @return [Proc]
81
+ attr_reader :block
82
+
52
83
  # @private
53
84
  #
54
85
  # Returns the block that will be used for method creattion
@@ -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 an class method from block
9
+ class ClassBlockDefinition < BlockDefinition
10
+ private
11
+
12
+ # @private
13
+ #
14
+ # Method used to define a class method
15
+ #
16
+ # @return [Symbol] Always :define_singleton_method
17
+ def method_definer
18
+ :define_singleton_method
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ class MethodDefinition
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # Module responsible for building class method definitions
9
+ module ClassMethodDefinition
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 With cache
24
+ # klass = Class.new
25
+ #
26
+ # method_definition = Sinclair::MethodDefinition::InstanceMethodDefinition.from(
27
+ # :sequence, cached: true
28
+ # ) do
29
+ # @x = @x.to_i ** 2 + 1
30
+ # end
31
+ #
32
+ # method_definition.build(klass)
33
+ #
34
+ # klass.sequence # returns 1
35
+ # klass.sequence # returns 1
36
+ #
37
+ # klass.instance_variable_get(:@x) # returns 1
38
+ # klass.instance_variable_get(:@sequence) # returns 1
39
+ #
40
+ # @return MethodDefinition
41
+ def self.from(name, code = nil, **options, &block)
42
+ if block
43
+ ClassBlockDefinition.new(name, **options, &block)
44
+ else
45
+ ClassStringDefinition.new(name, code, **options)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ 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 a method from string
9
+ class ClassStringDefinition < StringDefinition
10
+ private
11
+
12
+ # @private
13
+ #
14
+ # String used when defining method
15
+ #
16
+ # Class definition appends +self.+ to method name
17
+ #
18
+ # @return [String]
19
+ def method_name
20
+ "self.#{name}"
21
+ end
22
+ end
23
+ end
24
+ end