sinclair 1.6.5 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +2 -2
- data/Dockerfile +2 -2
- data/README.md +3 -1
- data/config/check_specs.yml +3 -0
- data/config/yardstick.yml +7 -1
- data/lib/sinclair/config.rb +46 -0
- data/lib/sinclair/config_class.rb +15 -0
- data/lib/sinclair/configurable.rb +8 -0
- data/lib/sinclair/matchers/add_class_method.rb +16 -13
- data/lib/sinclair/matchers/add_class_method_to.rb +9 -23
- data/lib/sinclair/matchers/add_instance_method.rb +16 -18
- data/lib/sinclair/matchers/add_instance_method_to.rb +12 -16
- data/lib/sinclair/matchers/add_method.rb +39 -30
- data/lib/sinclair/matchers/add_method_to.rb +4 -56
- data/lib/sinclair/matchers/base.rb +45 -0
- data/lib/sinclair/matchers/change_class_method.rb +42 -0
- data/lib/sinclair/matchers/change_class_method_on.rb +64 -0
- data/lib/sinclair/matchers/change_instance_method.rb +42 -0
- data/lib/sinclair/matchers/change_instance_method_on.rb +98 -0
- data/lib/sinclair/matchers/change_method_on.rb +25 -0
- data/lib/sinclair/matchers/method_to.rb +82 -0
- data/lib/sinclair/matchers.rb +38 -30
- data/lib/sinclair/options/class_methods.rb +95 -0
- data/lib/sinclair/options.rb +10 -60
- data/lib/sinclair/version.rb +1 -1
- data/sinclair.gemspec +12 -12
- data/spec/integration/readme/my_class_spec.rb +1 -1
- data/spec/integration/yard/sinclair/config_spec.rb +27 -0
- data/spec/integration/yard/sinclair/options_parser_spec.rb +9 -0
- data/spec/lib/sinclair/config_class_spec.rb +1 -33
- data/spec/lib/sinclair/config_spec.rb +71 -0
- data/spec/lib/sinclair/matchers/add_class_method_to_spec.rb +40 -16
- data/spec/lib/sinclair/matchers/add_instance_method_to_spec.rb +36 -12
- data/spec/lib/sinclair/matchers/change_class_method_on_spec.rb +138 -0
- data/spec/lib/sinclair/matchers/change_class_method_spec.rb +38 -0
- data/spec/lib/sinclair/matchers/change_instance_method_on_spec.rb +149 -0
- data/spec/lib/sinclair/matchers/change_instance_method_spec.rb +38 -0
- data/spec/lib/sinclair/matchers_spec.rb +30 -0
- data/spec/lib/sinclair/options/class_methods_spec.rb +255 -0
- data/spec/lib/sinclair/options_spec.rb +28 -237
- data/spec/support/models/builder_options.rb +7 -0
- data/spec/support/models/login_configurable.rb +7 -0
- data/spec/support/models/open_options.rb +7 -0
- data/spec/support/shared_examples/config.rb +48 -0
- metadata +43 -28
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Checks if a class method was changed
|
9
|
+
# by the call of a block
|
10
|
+
#
|
11
|
+
# This is used with a RSpec DSL method
|
12
|
+
# change_class_method(method_name).on(class_object)
|
13
|
+
class ChangeClassMethodOn < ChangeMethodOn
|
14
|
+
# @param [Class] klass
|
15
|
+
# Class where the class method should be added to
|
16
|
+
#
|
17
|
+
# @param method_name [SYmbol,String] method name
|
18
|
+
def initialize(target, method_name)
|
19
|
+
@klass = target
|
20
|
+
super(method_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return expectaton description
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
def description
|
27
|
+
"change class method '#{method_name}' on #{klass}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns message on expectation failure
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
def failure_message_for_should
|
34
|
+
"expected class method '#{method_name}' to be changed on #{klass} but " \
|
35
|
+
"#{initial_state ? "it didn't" : "it didn't exist"}"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns message on expectation failure for negative expectation
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
def failure_message_for_should_not
|
42
|
+
"expected class method '#{method_name}' not to be changed on #{klass} but it was"
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Checks if class has instance method defined
|
48
|
+
#
|
49
|
+
# @return [Boolean]
|
50
|
+
def state
|
51
|
+
klass.methods(false).include?(method_name.to_sym) \
|
52
|
+
&& klass.method(method_name)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Raises when block was not given
|
56
|
+
#
|
57
|
+
# @raise SyntaxError
|
58
|
+
def raise_block_syntax_error
|
59
|
+
raise SyntaxError, 'Block not received by the `change_class_method_on` matcher. ' \
|
60
|
+
'Perhaps you want to use `{ ... }` instead of do/end?'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# AddInstanceMethod is able to build an instance of
|
9
|
+
# {Sinclair::Matchers::ChangeInstanceMethodOn}
|
10
|
+
class ChangeInstanceMethod < Base
|
11
|
+
include AddMethod
|
12
|
+
|
13
|
+
# @api public
|
14
|
+
#
|
15
|
+
# Builds final matcher
|
16
|
+
#
|
17
|
+
# @return [Sinclair::Matchers::ChangeInstanceMethodOn]
|
18
|
+
alias on to
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# @private
|
23
|
+
#
|
24
|
+
# Error description on wrong usage
|
25
|
+
#
|
26
|
+
# @return String
|
27
|
+
def matcher_error
|
28
|
+
'You should specify which instance the method is being changed on' \
|
29
|
+
"change_method(:#{method_name}).on(instance)"
|
30
|
+
end
|
31
|
+
|
32
|
+
# @private
|
33
|
+
#
|
34
|
+
# Class of the real matcher
|
35
|
+
#
|
36
|
+
# @return [Class<Sinclair::Matchers::Base>]
|
37
|
+
def add_method_to_class
|
38
|
+
ChangeInstanceMethodOn
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
#
|
8
|
+
# Checks if a method was changed
|
9
|
+
# by the call of a block
|
10
|
+
#
|
11
|
+
# This is used with a RSpec DSL method
|
12
|
+
# change_method(method_name).on(class_object)
|
13
|
+
class ChangeInstanceMethodOn < ChangeMethodOn
|
14
|
+
# @overload initialize(klass, method_name)
|
15
|
+
# @param [Class] klass
|
16
|
+
# class where the method should be added to
|
17
|
+
#
|
18
|
+
# @overload initialize(instance, method_name)
|
19
|
+
# @param [Object] instance
|
20
|
+
# instance of the class where the method should be added to
|
21
|
+
#
|
22
|
+
# @param method_name [Symbol,String] method name
|
23
|
+
def initialize(target, method_name)
|
24
|
+
if target.is_a?(Class)
|
25
|
+
@klass = target
|
26
|
+
else
|
27
|
+
@instance = target
|
28
|
+
end
|
29
|
+
|
30
|
+
super(method_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returnst expectaton description
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
def description
|
37
|
+
"change method '#{method_name}' on #{klass} instances"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns message on expectation failure
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
def failure_message_for_should
|
44
|
+
"expected '#{method_name}' to be changed on #{klass} but " \
|
45
|
+
"#{initial_state ? "it didn't" : "it didn't exist"}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns message on expectation failure for negative expectation
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
def failure_message_for_should_not
|
52
|
+
"expected '#{method_name}' not to be changed on #{klass} but it was"
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
# @method instance
|
58
|
+
# @api private
|
59
|
+
# @private
|
60
|
+
#
|
61
|
+
# Instance of the class where the method should be added
|
62
|
+
#
|
63
|
+
# @return [Object]
|
64
|
+
attr_reader :instance
|
65
|
+
|
66
|
+
# @private
|
67
|
+
#
|
68
|
+
# Class to be analised
|
69
|
+
#
|
70
|
+
# @return [Class]
|
71
|
+
def klass
|
72
|
+
@klass ||= instance.class
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# @private
|
78
|
+
#
|
79
|
+
# Checks if class has instance method defined
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
def state
|
83
|
+
klass.method_defined?(method_name) &&
|
84
|
+
klass.instance_method(method_name)
|
85
|
+
end
|
86
|
+
|
87
|
+
# @private
|
88
|
+
#
|
89
|
+
# Raises when block was not given
|
90
|
+
#
|
91
|
+
# @raise SyntaxError
|
92
|
+
def raise_block_syntax_error
|
93
|
+
raise SyntaxError, 'Block not received by the `change_instance_method_on` matcher. ' \
|
94
|
+
'Perhaps you want to use `{ ... }` instead of do/end?'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
# @author darthjee
|
7
|
+
# @abstract
|
8
|
+
#
|
9
|
+
# Base class for change_method_on matcher
|
10
|
+
class ChangeMethodOn < Base
|
11
|
+
include MethodTo
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# @private
|
16
|
+
#
|
17
|
+
# Checks if a method was changed
|
18
|
+
#
|
19
|
+
# @return Boolean
|
20
|
+
def check
|
21
|
+
initial_state && initial_state != final_state
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Sinclair
|
4
|
+
module Matchers
|
5
|
+
# @api private
|
6
|
+
#
|
7
|
+
# Common methods on final matchers
|
8
|
+
module MethodTo
|
9
|
+
# Used for other versions of rspec
|
10
|
+
#
|
11
|
+
# Some versions call failure_message, others
|
12
|
+
# call failure_message_for_should
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
def failure_message
|
16
|
+
failure_message_for_should
|
17
|
+
end
|
18
|
+
|
19
|
+
# Used for other versions of rspec
|
20
|
+
#
|
21
|
+
# Some versions call failure_message_when_negated, others
|
22
|
+
# call failure_message_for_should_not
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def failure_message_when_negated
|
26
|
+
failure_message_for_should_not
|
27
|
+
end
|
28
|
+
|
29
|
+
# Checks if expectation is true or not
|
30
|
+
#
|
31
|
+
# @return [Boolean] expectation check
|
32
|
+
def matches?(event_proc)
|
33
|
+
return false unless event_proc.is_a?(Proc)
|
34
|
+
|
35
|
+
raise_block_syntax_error if block_given?
|
36
|
+
perform_change(event_proc)
|
37
|
+
check
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
# @method klass
|
43
|
+
# @api private
|
44
|
+
# @private
|
45
|
+
#
|
46
|
+
# Class where class method should be added to
|
47
|
+
#
|
48
|
+
# @return [Class]
|
49
|
+
attr_reader :klass
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @method initial_state
|
54
|
+
# @api private
|
55
|
+
# @private
|
56
|
+
#
|
57
|
+
# State before running the block
|
58
|
+
#
|
59
|
+
# @return [Object]
|
60
|
+
|
61
|
+
# @method final_state
|
62
|
+
# @api private
|
63
|
+
# @private
|
64
|
+
#
|
65
|
+
# State after running the block
|
66
|
+
#
|
67
|
+
# @return [Object]
|
68
|
+
attr_reader :initial_state, :final_state
|
69
|
+
|
70
|
+
# @private
|
71
|
+
#
|
72
|
+
# Call block to check if it aded a method or not
|
73
|
+
#
|
74
|
+
# @return [Boolan]
|
75
|
+
def perform_change(event_proc)
|
76
|
+
@initial_state = state
|
77
|
+
event_proc.call
|
78
|
+
@final_state = state
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/sinclair/matchers.rb
CHANGED
@@ -7,33 +7,21 @@ class Sinclair
|
|
7
7
|
# Matchers module will have the DSL to be included in RSpec in order to have
|
8
8
|
# access to the matchers
|
9
9
|
#
|
10
|
-
# @example
|
11
|
-
# RSpec.configure do |config|
|
12
|
-
# config.include Sinclair::Matchers
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# class MyModel
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# RSpec.describe 'my test' do
|
19
|
-
# let(:klass) { Class.new(MyModel) }
|
20
|
-
# let(:builder) { Sinclair.new(klass) }
|
21
|
-
#
|
22
|
-
# before do
|
23
|
-
# builder.add_method(:class_name, 'self.class.name')
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# it do
|
27
|
-
# expect { builder.build }.to add_method(:class_name).to(klass)
|
28
|
-
# end
|
29
|
-
# end
|
10
|
+
# @example (see Sinclair::Matchers::AddMethod#to)
|
30
11
|
module Matchers
|
31
|
-
autoload :
|
32
|
-
autoload :AddInstanceMethod,
|
33
|
-
autoload :AddClassMethod,
|
34
|
-
autoload :
|
35
|
-
autoload :
|
36
|
-
autoload :
|
12
|
+
autoload :Base, 'sinclair/matchers/base'
|
13
|
+
autoload :AddInstanceMethod, 'sinclair/matchers/add_instance_method'
|
14
|
+
autoload :AddClassMethod, 'sinclair/matchers/add_class_method'
|
15
|
+
autoload :AddMethod, 'sinclair/matchers/add_method'
|
16
|
+
autoload :AddMethodTo, 'sinclair/matchers/add_method_to'
|
17
|
+
autoload :AddInstanceMethodTo, 'sinclair/matchers/add_instance_method_to'
|
18
|
+
autoload :AddClassMethodTo, 'sinclair/matchers/add_class_method_to'
|
19
|
+
autoload :ChangeClassMethod, 'sinclair/matchers/change_class_method'
|
20
|
+
autoload :ChangeInstanceMethod, 'sinclair/matchers/change_instance_method'
|
21
|
+
autoload :ChangeMethodOn, 'sinclair/matchers/change_method_on'
|
22
|
+
autoload :ChangeClassMethodOn, 'sinclair/matchers/change_class_method_on'
|
23
|
+
autoload :ChangeInstanceMethodOn, 'sinclair/matchers/change_instance_method_on'
|
24
|
+
autoload :MethodTo, 'sinclair/matchers/method_to'
|
37
25
|
|
38
26
|
# DSL to AddInstanceMethod
|
39
27
|
#
|
@@ -41,8 +29,8 @@ class Sinclair
|
|
41
29
|
# @example (see Sinclair::Matchers::AddInstanceMethod#to)
|
42
30
|
#
|
43
31
|
# @return [AddInstanceMethod] RSpec Matcher
|
44
|
-
def add_method(
|
45
|
-
Sinclair::Matchers::AddInstanceMethod.new(
|
32
|
+
def add_method(method_name)
|
33
|
+
Sinclair::Matchers::AddInstanceMethod.new(method_name)
|
46
34
|
end
|
47
35
|
|
48
36
|
# DSL to AddClassMethod
|
@@ -51,8 +39,28 @@ class Sinclair
|
|
51
39
|
# @example (see Sinclair::Matchers::AddClassMethod#to)
|
52
40
|
#
|
53
41
|
# @return [AddClassMethod] RSpec Matcher
|
54
|
-
def add_class_method(
|
55
|
-
Sinclair::Matchers::AddClassMethod.new(
|
42
|
+
def add_class_method(method_name)
|
43
|
+
Sinclair::Matchers::AddClassMethod.new(method_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
# DSL to ChangeInstanceMethod
|
47
|
+
#
|
48
|
+
# @example (see Sinclair::Matchers)
|
49
|
+
# @example (see Sinclair::Matchers::ChangeInstanceMethod#to)
|
50
|
+
#
|
51
|
+
# @return [ChangeInstanceMethod] RSpec Matcher
|
52
|
+
def change_method(method_name)
|
53
|
+
Sinclair::Matchers::ChangeInstanceMethod.new(method_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
# DSL to ChangeClassMethod
|
57
|
+
#
|
58
|
+
# @example (see Sinclair::Matchers)
|
59
|
+
# @example (see Sinclair::Matchers::ChangeClassMethod#to)
|
60
|
+
#
|
61
|
+
# @return [ChangeClassMethod] RSpec Matcher
|
62
|
+
def change_class_method(method_name)
|
63
|
+
Sinclair::Matchers::ChangeClassMethod.new(method_name)
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
class Sinclair
|
6
|
+
class Options
|
7
|
+
# Class Methods for {Sinclai::Options}
|
8
|
+
module ClassMethods
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
# returns invalid options
|
12
|
+
#
|
13
|
+
# @return [Array<Symbol>]
|
14
|
+
def invalid_options_in(names)
|
15
|
+
names.map(&:to_sym) - allowed_options.to_a
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
#
|
20
|
+
# Allow new option
|
21
|
+
#
|
22
|
+
# This does not create the method
|
23
|
+
#
|
24
|
+
# @param name [String,Symbol] options to be allowed
|
25
|
+
#
|
26
|
+
# @return [Set<Symbol>]
|
27
|
+
def allow(name)
|
28
|
+
allowed_options << name.to_sym
|
29
|
+
end
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
# @private
|
33
|
+
#
|
34
|
+
# Options allowed when initializing options
|
35
|
+
#
|
36
|
+
# @return [Set<Symbol>]
|
37
|
+
def allowed_options
|
38
|
+
@allowed_options ||= superclass.try(:allowed_options).dup || Set.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
#
|
43
|
+
# checks if class skips initialization validation
|
44
|
+
#
|
45
|
+
# @return [TrueClass,FalseClass]
|
46
|
+
def skip_validation?
|
47
|
+
@skip_validation ||= superclass.try(:skip_validation?) || false
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api public
|
51
|
+
#
|
52
|
+
# Add available options
|
53
|
+
#
|
54
|
+
# @example (see Options)
|
55
|
+
#
|
56
|
+
# @return (see Sinclair#build)
|
57
|
+
#
|
58
|
+
# @overload with_options(*options)
|
59
|
+
# @param options [Array<Symbol>] list of accepted
|
60
|
+
# options
|
61
|
+
# @overload with_options(*options, **defaults)
|
62
|
+
# @param options [Array<Symbol>] list of accepted
|
63
|
+
# options
|
64
|
+
# @param defaults [Hash<Symbol,Object>] default options
|
65
|
+
# hash
|
66
|
+
def with_options(*options)
|
67
|
+
Builder.new(self, *options).build
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api public
|
71
|
+
#
|
72
|
+
# Changes class to skip attributes validation
|
73
|
+
#
|
74
|
+
# when initializing options, options
|
75
|
+
# will accept any arguments when validation
|
76
|
+
# is skipped
|
77
|
+
#
|
78
|
+
# @return [TrueClass]
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# class BuilderOptions < Sinclair::Options
|
82
|
+
# with_options :name
|
83
|
+
#
|
84
|
+
# skip_validation
|
85
|
+
# end
|
86
|
+
# options = BuilderOptions.new(name: 'Joe', age: 10)
|
87
|
+
#
|
88
|
+
# options.name # returns 'Joe'
|
89
|
+
# options.try(:age) # returns nil
|
90
|
+
def skip_validation
|
91
|
+
@skip_validation = true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/sinclair/options.rb
CHANGED
@@ -20,64 +20,10 @@ class Sinclair
|
|
20
20
|
# options.port # returns 8080
|
21
21
|
# options.protocol # returns 'https'
|
22
22
|
class Options
|
23
|
-
autoload :Builder,
|
23
|
+
autoload :Builder, 'sinclair/options/builder'
|
24
|
+
autoload :ClassMethods, 'sinclair/options/class_methods'
|
24
25
|
|
25
|
-
|
26
|
-
# @api private
|
27
|
-
#
|
28
|
-
# returns invalid options
|
29
|
-
#
|
30
|
-
# @return [Array<Symbol>]
|
31
|
-
def invalid_options_in(names)
|
32
|
-
names.map(&:to_sym) - allowed_options.to_a
|
33
|
-
end
|
34
|
-
|
35
|
-
# @api private
|
36
|
-
#
|
37
|
-
# Allow new option
|
38
|
-
#
|
39
|
-
# This does not create the method
|
40
|
-
#
|
41
|
-
# @param name [String,Symbol] options to be allowed
|
42
|
-
#
|
43
|
-
# @return [Set<Symbol>]
|
44
|
-
def allow(name)
|
45
|
-
allowed_options << name.to_sym
|
46
|
-
end
|
47
|
-
|
48
|
-
# @api private
|
49
|
-
# @private
|
50
|
-
#
|
51
|
-
# Options allowed when initializing options
|
52
|
-
#
|
53
|
-
# @return [Set<Symbol>]
|
54
|
-
def allowed_options
|
55
|
-
@allowed_options ||= superclass.try(:allowed_options).dup || Set.new
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# @api public
|
61
|
-
# @!visibility public
|
62
|
-
#
|
63
|
-
# Add available options
|
64
|
-
#
|
65
|
-
# @example (see Options)
|
66
|
-
#
|
67
|
-
# @return (see Sinclair#build)
|
68
|
-
#
|
69
|
-
# @overload with_options(*options)
|
70
|
-
# @param options [Array<Symbol>] list of accepted
|
71
|
-
# options
|
72
|
-
# @overload with_options(*options, **defaults)
|
73
|
-
# @param options [Array<Symbol>] list of accepted
|
74
|
-
# options
|
75
|
-
# @param defaults [Hash<Symbol,Object>] default options
|
76
|
-
# hash
|
77
|
-
def with_options(*options)
|
78
|
-
Builder.new(self, *options).build
|
79
|
-
end
|
80
|
-
end
|
26
|
+
extend ClassMethods
|
81
27
|
|
82
28
|
# @param options [Hash] hash with options (see {.options}, {.with_options})
|
83
29
|
# @example (see Options)
|
@@ -108,7 +54,7 @@ class Sinclair
|
|
108
54
|
# # protocol: 'https'
|
109
55
|
# # }
|
110
56
|
def to_h
|
111
|
-
|
57
|
+
allowed_options.inject({}) do |hash, option|
|
112
58
|
hash.merge(option => public_send(option))
|
113
59
|
end
|
114
60
|
end
|
@@ -121,13 +67,15 @@ class Sinclair
|
|
121
67
|
def ==(other)
|
122
68
|
return false unless self.class == other.class
|
123
69
|
|
124
|
-
|
70
|
+
allowed_options.all? do |name|
|
125
71
|
public_send(name) == other.public_send(name)
|
126
72
|
end
|
127
73
|
end
|
128
74
|
|
129
75
|
private
|
130
76
|
|
77
|
+
delegate :allowed_options, :skip_validation?, :invalid_options_in, to: :class
|
78
|
+
|
131
79
|
# @private
|
132
80
|
# @api private
|
133
81
|
#
|
@@ -137,7 +85,9 @@ class Sinclair
|
|
137
85
|
#
|
138
86
|
# @return [NilClass]
|
139
87
|
def check_options(options)
|
140
|
-
|
88
|
+
return if skip_validation?
|
89
|
+
|
90
|
+
invalid_keys = invalid_options_in(options.keys)
|
141
91
|
|
142
92
|
return if invalid_keys.empty?
|
143
93
|
|
data/lib/sinclair/version.rb
CHANGED
data/sinclair.gemspec
CHANGED
@@ -21,20 +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', '
|
25
|
-
gem.add_development_dependency 'pry', '0.
|
26
|
-
gem.add_development_dependency 'pry-nav', '0.
|
24
|
+
gem.add_development_dependency 'bundler', '2.3.20'
|
25
|
+
gem.add_development_dependency 'pry', '0.14.1'
|
26
|
+
gem.add_development_dependency 'pry-nav', '1.0.0'
|
27
27
|
gem.add_development_dependency 'rake', '13.0.1'
|
28
|
-
gem.add_development_dependency 'reek', '
|
29
|
-
gem.add_development_dependency 'rspec', '3.
|
30
|
-
gem.add_development_dependency 'rspec-core', '3.
|
31
|
-
gem.add_development_dependency 'rspec-expectations', '3.
|
32
|
-
gem.add_development_dependency 'rspec-mocks', '3.
|
33
|
-
gem.add_development_dependency 'rspec-support', '3.
|
28
|
+
gem.add_development_dependency 'reek', '6.0.3'
|
29
|
+
gem.add_development_dependency 'rspec', '3.11.0'
|
30
|
+
gem.add_development_dependency 'rspec-core', '3.11.0'
|
31
|
+
gem.add_development_dependency 'rspec-expectations', '3.11.0'
|
32
|
+
gem.add_development_dependency 'rspec-mocks', '3.11.1'
|
33
|
+
gem.add_development_dependency 'rspec-support', '3.11.0'
|
34
34
|
gem.add_development_dependency 'rubocop', '0.80.1'
|
35
35
|
gem.add_development_dependency 'rubocop-rspec', '1.38.1'
|
36
|
-
gem.add_development_dependency 'rubycritic', '4.
|
37
|
-
gem.add_development_dependency 'simplecov', '0.
|
38
|
-
gem.add_development_dependency 'yard', '0.9.
|
36
|
+
gem.add_development_dependency 'rubycritic', '4.7.0'
|
37
|
+
gem.add_development_dependency 'simplecov', '0.21.2'
|
38
|
+
gem.add_development_dependency 'yard', '0.9.27'
|
39
39
|
gem.add_development_dependency 'yardstick', '0.9.9'
|
40
40
|
end
|
@@ -24,5 +24,32 @@ describe Sinclair::Config do
|
|
24
24
|
.to eq('{"password":null,"username":"bob"}')
|
25
25
|
end
|
26
26
|
end
|
27
|
+
|
28
|
+
describe '#options' do
|
29
|
+
subject(:config) { configurable.config }
|
30
|
+
|
31
|
+
let(:configurable) { LoginConfigurable }
|
32
|
+
|
33
|
+
before do
|
34
|
+
LoginConfigurable.configure do |conf|
|
35
|
+
conf.username :some_username
|
36
|
+
conf.password :some_password
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns options with correct values' do
|
41
|
+
expect(config.options.username).to eq(:some_username)
|
42
|
+
expect(config.options.password).to eq(:some_password)
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when merging with given attributes' do
|
46
|
+
subject(:options) { config.options(password: :correct_password) }
|
47
|
+
|
48
|
+
it 'returns options with custom values' do
|
49
|
+
expect(options.username).to eq(:some_username)
|
50
|
+
expect(options.password).to eq(:correct_password)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
27
54
|
end
|
28
55
|
end
|