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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +5 -3
- data/.rubocop.yml +20 -4
- data/Dockerfile +8 -4
- data/README.md +1 -1
- data/config/yardstick.yml +10 -35
- data/lib/sinclair.rb +87 -18
- data/lib/sinclair/config.rb +3 -0
- data/lib/sinclair/config/methods_builder.rb +15 -1
- data/lib/sinclair/config_builder.rb +1 -0
- data/lib/sinclair/config_class.rb +1 -0
- data/lib/sinclair/config_factory.rb +15 -0
- data/lib/sinclair/configurable.rb +1 -0
- data/lib/sinclair/matchers.rb +20 -6
- data/lib/sinclair/matchers/add_class_method.rb +56 -0
- data/lib/sinclair/matchers/add_class_method_to.rb +98 -0
- data/lib/sinclair/matchers/add_instance_method.rb +85 -0
- data/lib/sinclair/matchers/add_instance_method_to.rb +119 -0
- data/lib/sinclair/matchers/add_method.rb +11 -73
- data/lib/sinclair/matchers/add_method_to.rb +13 -111
- data/lib/sinclair/method_definition.rb +18 -58
- data/lib/sinclair/method_definition/block_definition.rb +37 -6
- data/lib/sinclair/method_definition/class_block_definition.rb +22 -0
- data/lib/sinclair/method_definition/class_method_definition.rb +50 -0
- data/lib/sinclair/method_definition/class_string_definition.rb +24 -0
- data/lib/sinclair/method_definition/instance_block_definition.rb +22 -0
- data/lib/sinclair/method_definition/instance_method_definition.rb +48 -0
- data/lib/sinclair/method_definition/instance_string_definition.rb +24 -0
- data/lib/sinclair/method_definition/string_definition.rb +39 -5
- data/lib/sinclair/method_definitions.rb +28 -0
- data/lib/sinclair/options_parser.rb +5 -0
- data/lib/sinclair/version.rb +1 -1
- data/sinclair.gemspec +16 -10
- data/spec/integration/yard/sinclair/matchers/add_class_method_spec.rb +23 -0
- data/spec/integration/yard/sinclair/matchers/add_class_method_to_spec.rb +19 -0
- data/spec/integration/yard/sinclair/matchers/{add_method_spec.rb → add_instance_method_spec.rb} +3 -3
- data/spec/integration/yard/sinclair/matchers/{add_method_to_spec.rb → add_instance_method_to_spec.rb} +1 -1
- data/spec/integration/yard/sinclair/method_definition/class_block_definition_spec.rb +34 -0
- data/spec/integration/yard/sinclair/method_definition/class_method_definition_spec.rb +28 -0
- data/spec/integration/yard/sinclair/method_definition/class_string_definition_spec.rb +23 -0
- data/spec/integration/yard/sinclair/method_definition/{block_definition_spec.rb → instance_block_definition_spec.rb} +2 -2
- data/spec/integration/yard/sinclair/method_definition/instance_method_definition_spec.rb +35 -0
- data/spec/integration/yard/sinclair/method_definition/{string_definition_spec.rb → instance_string_definition_spec.rb} +1 -1
- data/spec/integration/yard/sinclair_spec.rb +32 -5
- data/spec/lib/sinclair/matchers/add_class_method_spec.rb +36 -0
- data/spec/lib/sinclair/matchers/add_class_method_to_spec.rb +77 -0
- data/spec/lib/sinclair/matchers/{add_method_spec.rb → add_instance_method_spec.rb} +11 -4
- data/spec/lib/sinclair/matchers/{add_method_to_spec.rb → add_instance_method_to_spec.rb} +2 -2
- data/spec/lib/sinclair/matchers_spec.rb +17 -2
- data/spec/lib/sinclair/method_definition/class_block_definition_spec.rb +29 -0
- data/spec/lib/sinclair/method_definition/class_string_definition_spec.rb +27 -0
- data/spec/lib/sinclair/method_definition/{block_definition_spec.rb → instance_block_definition_spec.rb} +2 -2
- data/spec/lib/sinclair/method_definition/{string_definition_spec.rb → instance_string_definition_spec.rb} +2 -2
- data/spec/lib/sinclair/method_definition_spec.rb +52 -6
- data/spec/lib/sinclair_spec.rb +83 -0
- data/spec/support/models/dummy_class_builder.rb +11 -0
- data/spec/support/shared_examples/class_method_definition.rb +96 -0
- data/spec/support/shared_examples/{method_definition.rb → instance_method_definition.rb} +0 -0
- metadata +148 -45
- data/scripts/check_readme.sh +0 -6
- data/scripts/rubycritic.sh +0 -10
- data/spec/integration/sinclair/matchers_spec.rb +0 -99
- 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
|
-
#
|
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
|
-
# @
|
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.
|
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
|
-
# @
|
46
|
+
# @method method
|
121
47
|
# @private
|
122
|
-
|
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 :
|
12
|
-
autoload :
|
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
|
48
|
-
#
|
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
|
-
|
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
|
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::
|
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(
|
36
|
-
#
|
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(
|
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
|