sinclair 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
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