sinclair 1.2.1 → 1.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5d1b06127b9390b635b3f51e208b4e0e327e37bf3a983975256c998746c19ef
4
- data.tar.gz: c9ef323396888f3adbf13b1f2147856987c0ffb4f4ea05e8419f0440f2445c25
3
+ metadata.gz: 8078be623117ced163bf463e484e1e2553781dc3ebf379e48a98dc5c3e710079
4
+ data.tar.gz: 5edfd7356786a04ee94f5bfff56fd954e26b52b5fa4ef7eb3372ddd33ddb6c80
5
5
  SHA512:
6
- metadata.gz: a70f4147f03c3ef11467af1c5de31c4fa446368496126ce588875016cbbac17287f3c736c7d040b42e5f6cbff797cdfb1b5002db4475451541114486a554b14e
7
- data.tar.gz: 824f2cf65e9442e002b8010e4ed2f2ba3228043cba122358538aa497cc0015b1ea64a6acac1bce68f8f321d1c1c624ce27e97030775554bca9b33ec55da76671
6
+ metadata.gz: 03b32dcf796be1331442a673040264bc2cb215f1ad2eb657aaf416f76bea0e6aaca71ccb8bd356e5c9ab094dc31f4d2a0c3cc4dc607ccb39db429b864b5e785c
7
+ data.tar.gz: 28bd3ed7dea51f96d82bdbbdb64588762cc017ab92d8847045dbf33beb8aa83abc71869ff5e55f4f8dc72f4f29f4f9907596702acb7ab5f456c43bc0b92e902b
data/.circleci/config.yml CHANGED
@@ -2,7 +2,7 @@ version: 2
2
2
  jobs:
3
3
  build:
4
4
  docker:
5
- - image: darthjee/circleci_ruby_gems:0.0.1
5
+ - image: darthjee/circleci_ruby_gems:0.1.0
6
6
  steps:
7
7
  - checkout
8
8
  - run:
@@ -26,3 +26,6 @@ jobs:
26
26
  - run:
27
27
  name: Check version documentation
28
28
  command: scripts/check_readme.sh
29
+ - run:
30
+ name: Rubycritcs check
31
+ command: scripts/rubycritic.sh
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ doc
6
6
  .yardoc/
7
7
  measurement/
8
8
  **/*.swp
9
+ rubycritic/
data/Dockerfile CHANGED
@@ -1,6 +1,26 @@
1
- FROM darthjee/ruby_gems:0.0.1
1
+ FROM darthjee/ruby_gems:0.0.1 as base
2
+ FROM darthjee/scripts:0.0.2 as scripts
3
+
4
+ ######################################
5
+
6
+ FROM base as builder
2
7
 
3
- USER app
4
8
  COPY --chown=app ./ /home/app/app/
9
+ COPY --chown=app:app --from=scripts /home/scripts/ ./
10
+
11
+ ENV HOME_DIR /home/app
12
+ RUN /bin/bash bundle_builder.sh
5
13
 
6
- RUN bundle install
14
+ #######################
15
+ #FINAL IMAGE
16
+ FROM base
17
+
18
+ USER root
19
+
20
+ COPY --chown=app:app --from=builder /home/app/bundle/gems /usr/local/bundle/gems
21
+ COPY --chown=app:app --from=builder /home/app/bundle/cache /usr/local/bundle/cache
22
+ COPY --chown=app:app --from=builder /home/app/bundle/specifications /usr/local/bundle/specifications
23
+ COPY --chown=app:app --from=builder /home/app/bundle/bin /usr/local/bundle/bin
24
+ COPY --chown=app:app --from=builder /home/app/bundle/extensions /usr/local/bundle/extensions
25
+
26
+ USER app
data/README.md CHANGED
@@ -12,7 +12,7 @@ This gem helps the creation of complex concern with class methods
12
12
 
13
13
  Yard Documentation
14
14
  -------------------
15
- https://www.rubydoc.info/gems/sinclair/1.2.1
15
+ https://www.rubydoc.info/gems/sinclair/1.3.0
16
16
 
17
17
  Installation
18
18
  ---------------
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
5
  require 'yardstick/rake/measurement'
6
6
  require './config/yardstick'
7
+ require './config/rubycritc'
7
8
 
8
9
  RSpec::Core::RakeTask.new
9
10
 
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubycritic/rake_task'
4
+
5
+ RubyCritic::RakeTask.new do |task|
6
+ options = %w[
7
+ --path rubycritic/
8
+ --no-browser
9
+ ]
10
+ task.options = options.join(' ')
11
+ task.paths = %w[lib]
12
+ end
data/config/yardstick.yml CHANGED
@@ -31,6 +31,9 @@ rules:
31
31
  - Sinclair::OptionsParser#options
32
32
  - Sinclair::OptionsParser#options_object
33
33
  - Sinclair::Matchers::AddMethodTo#raise_block_syntax_error
34
+ - Sinclair::ConfigFactory#initialize
35
+ - Sinclair::ConfigFactory#config_class
36
+ - Sinclair::ConfigFactory#config_attributes
34
37
  Summary::Presence:
35
38
  enabled: true
36
39
  exclude:
@@ -43,6 +46,9 @@ rules:
43
46
  - Sinclair::MethodDefinition#block
44
47
  - Sinclair::OptionsParser#options
45
48
  - Sinclair::OptionsParser#options_object
49
+ - Sinclair::ConfigFactory#initialize
50
+ - Sinclair::ConfigFactory#config_class
51
+ - Sinclair::ConfigFactory#config_attributes
46
52
  Summary::Length:
47
53
  enabled: true
48
54
  exclude: []
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ # Base class for configuration when using {Configurable}
5
+ #
6
+ # The methods will be added later by {ConfigFactory}
7
+ #
8
+ # The instance variables will be set by {ConfigBuilder}
9
+ class Config
10
+ end
11
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ # @api private
5
+ #
6
+ # Class responsible for setting the values on configuration
7
+ #
8
+ # @example
9
+ # class MyConfig
10
+ # attr_reader :name, :config
11
+ # end
12
+ #
13
+ # config = MyConfig.new
14
+ #
15
+ # builder = Sinclair::ConfigBuilder.new(config, :name)
16
+ #
17
+ # builder.instance_eval { |c| c.name 'John' }
18
+ #
19
+ # config.name # returns 'John'
20
+ class ConfigBuilder
21
+ # A new instance of ConfigBuilder
22
+ #
23
+ # @param config [Sinclair::Config] config object to be build
24
+ # config object has no attribute setters (only readers)
25
+ # so all attributes are set as instance variable
26
+ #
27
+ # @param config_attributes [Array<Symbol>] list of attributes
28
+ # that can be set on config (expecting that config has
29
+ # the right attribute readers)
30
+ def initialize(config, *config_attributes)
31
+ @config = config
32
+ @config_attributes = config_attributes
33
+ end
34
+
35
+ private
36
+
37
+ # @private
38
+ #
39
+ # Method called for methods missing
40
+ #
41
+ # When a method is missing, it is expected that it is the
42
+ # name of a variable to be set on config (as long as it was
43
+ # defined in the config_attributes_array)
44
+ #
45
+ # @param method_name [Symbol] name of the method called
46
+ # @param args [Array<Object>] arguments of the call
47
+ #
48
+ # @return [Object]
49
+ def method_missing(method_name, *args)
50
+ return super unless @config_attributes.include?(method_name)
51
+
52
+ @config.instance_variable_set("@#{method_name}", *args)
53
+ end
54
+
55
+ # @private
56
+ #
57
+ # Checks if method missing will catch the method called
58
+ #
59
+ # @return [TrueClass,FalseClass]
60
+ #
61
+ # @see #method_missing
62
+ def respond_to_missing?(method_name, include_private)
63
+ @config_attributes.include?(method_name) || super
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ # @api private
5
+ #
6
+ # Class responsible for configuring the configuration class
7
+ #
8
+ # @example General usage
9
+ # factory = Sinclair::ConfigFactory.new
10
+ # factory.add_configs(:name)
11
+ # factory.configure { |c| c.name 'John' }
12
+ #
13
+ # config = factory.config
14
+ #
15
+ # config.class.superclass # returns Sinclair::Config
16
+ # factory.config.equal?(config) # returns true
17
+ # config.name # returns 'John'
18
+ class ConfigFactory
19
+ # @param config_class [Class] configuration class to be used
20
+ # @param config_attributes [Array<Symbol,String>] list of possible configurations
21
+ def initialize(config_class: Class.new(Config), config_attributes: [])
22
+ @config_class = config_class
23
+ @config_attributes = config_attributes.dup
24
+ end
25
+
26
+ # Returns current instance of config
27
+ #
28
+ # the method returns the same instance until +reset_config+
29
+ # is called
30
+ #
31
+ # @return [Config,Object] the instance of given
32
+ # config_class. by default, this returns
33
+ # +Class.new(Config).new+
34
+ #
35
+ # @see #reset_config
36
+ #
37
+ # @example (see ConfigFactory)
38
+ def config
39
+ @config ||= config_class.new
40
+ end
41
+
42
+ # Cleans the current config instance
43
+ #
44
+ # After cleaning it, {#config} will generate a new
45
+ # instance
46
+ #
47
+ # @return [NilClass]
48
+ #
49
+ # @example
50
+ # factory = Sinclair::ConfigFactory.new
51
+ #
52
+ # config = factory.config
53
+ #
54
+ # factory.reset_config
55
+ #
56
+ # factory.config == config # returns false
57
+ def reset_config
58
+ @config = nil
59
+ end
60
+
61
+ # Adds possible configurations
62
+ #
63
+ # It change the configuration class adding methods
64
+ # and keeps track of those configurations so that
65
+ # {ConfigBuilder} is able to set those values when invoked
66
+ #
67
+ # @return [Array<Symbol>] all known config attributes
68
+ #
69
+ # @example Adding configuration name
70
+ # factory = Sinclair::ConfigFactory.new
71
+ # config = factory.config
72
+ #
73
+ # config.respond_to? :active
74
+ # # returns false
75
+ #
76
+ # factory.add_configs(:active)
77
+ #
78
+ # config.respond_to? :active
79
+ # # returns true
80
+ def add_configs(*attributes)
81
+ config_class.attr_reader(*attributes)
82
+ config_attributes.concat(attributes.map(&:to_sym))
83
+ end
84
+
85
+ # Set the values in the config
86
+ #
87
+ # The block given is evaluated by the {ConfigBuilder}
88
+ # where each method missed will be used to set a variable
89
+ # in the config
90
+ #
91
+ # @yield [ConfigBuilder] methods called in the block
92
+ # that are not present in {ConfigBuilder} are
93
+ # then set as instance variables of the config
94
+ #
95
+ # @return [Object] the result of the block
96
+ #
97
+ # @example Setting name on config
98
+ # class MyConfig
99
+ # attr_reader :name
100
+ # end
101
+ #
102
+ # factory = Sinclair::ConfigFactory.new(
103
+ # config_class: MyConfig,
104
+ # config_attributes: [:name]
105
+ # )
106
+ #
107
+ # config = factory.config
108
+ #
109
+ # factory.configure { name 'John' }
110
+ #
111
+ # config.name # returns 'John'
112
+ def configure(&block)
113
+ config_builder.instance_eval(&block)
114
+ end
115
+
116
+ # Returns a new instance of ConfigFactory
117
+ #
118
+ # the new instance will have the same
119
+ # config_attributes and for config_class a child
120
+ # of the current config_class
121
+ #
122
+ # This method is called when initializing {Configurable}
123
+ # config_factory and the superclass is also configurable
124
+ #
125
+ # This way, child classes from other {Configurable} classes
126
+ # will have a config_class that is a child from the original
127
+ # config_class
128
+ #
129
+ # @return [ConfigFactory]
130
+ def child
131
+ self.class.new(
132
+ config_class: Class.new(config_class),
133
+ config_attributes: config_attributes
134
+ )
135
+ end
136
+
137
+ private
138
+
139
+ # @private
140
+ attr_reader :config_class, :config_attributes
141
+
142
+ # @private
143
+ #
144
+ # Returns a builder capable of injecting variables into config
145
+ #
146
+ # @return [ConfigBuilder]
147
+ def config_builder
148
+ ConfigBuilder.new(config, *config_attributes)
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ # @api public
5
+ #
6
+ # Module capable of giving configuration capability
7
+ #
8
+ # By extending Configurable, class receives the methods public
9
+ # {ConfigFactory#config .config}, {ConfigFactory#reset_config .reset_config}
10
+ # and {ConfigFactory#configure .configure}
11
+ # and the private {#configurable_with .configurable_with}
12
+ #
13
+ # @see ConfigFactory
14
+ # @see ConfigBuilder
15
+ #
16
+ # @example
17
+ # class MyConfigurable
18
+ # extend Sinclair::Configurable
19
+ #
20
+ # configurable_with :host, :port
21
+ # end
22
+ #
23
+ # MyConfigurable.configure do
24
+ # host 'interstella.com'
25
+ # port 5555
26
+ # end
27
+ #
28
+ # MyConfigurable.config.host
29
+ # # returns 'interstella.com'
30
+ #
31
+ # MyConfigurable.config.port
32
+ # # returns 5555
33
+ #
34
+ # MyConfigurable.reset
35
+ #
36
+ # MyConfigurable.config.host
37
+ # # returns nil
38
+ module Configurable
39
+ delegate :config, :reset_config, :configure, to: :config_factory
40
+
41
+ protected
42
+
43
+ # @api private
44
+ #
45
+ # @private
46
+ #
47
+ # Generates a config factory
48
+ #
49
+ # When the current class is a child of a class extending
50
+ # {Configurable}, config_factory will be initialized with
51
+ # parameters to generate a configuration child from the
52
+ # original factory config
53
+ #
54
+ # @see ConfigFactory#child
55
+ #
56
+ # @return [ConfigFactory]
57
+ def config_factory
58
+ @config_factory ||= if superclass.is_a?(Configurable)
59
+ superclass.config_factory.child
60
+ else
61
+ ConfigFactory.new
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ # @visibility public
68
+ #
69
+ # Adds a configuration option to config class
70
+ #
71
+ # @return [Array<Symbol>] list of possible
72
+ # configurations
73
+ #
74
+ # @see ConfigFactory#add_configs
75
+ #
76
+ # @example (see Configurable)
77
+ def configurable_with(*attributes)
78
+ config_factory.add_configs(*attributes)
79
+ end
80
+ end
81
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '1.2.1'
4
+ VERSION = '1.3.0'
5
5
  end
data/lib/sinclair.rb CHANGED
@@ -29,6 +29,10 @@ class Sinclair
29
29
 
30
30
  autoload :VERSION, 'sinclair/version'
31
31
  autoload :MethodDefinition, 'sinclair/method_definition'
32
+ autoload :Config, 'sinclair/config'
33
+ autoload :ConfigBuilder, 'sinclair/config_builder'
34
+ autoload :ConfigFactory, 'sinclair/config_factory'
35
+ autoload :Configurable, 'sinclair/configurable'
32
36
 
33
37
  include OptionsParser
34
38
 
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ DIFF_LIST=$(git diff --name-only $CIRCLE_SHA1 $(git merge-base $CIRCLE_SHA1 origin/master) | grep "^lib/")
4
+
5
+ if [ ! -z "$DIFF_LIST" ]; then
6
+ mkdir -p tmp/rubycritic/compare
7
+ bundle exec rubycritic --format console --branch origin/master -t 0 $DIFF_LIST
8
+ else
9
+ echo "No changes detected. Skipping rubycritic..."
10
+ fi
data/sinclair.gemspec CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |gem|
27
27
  gem.add_development_dependency 'rspec', '>= 3.8'
28
28
  gem.add_development_dependency 'rubocop', '0.58.1'
29
29
  gem.add_development_dependency 'rubocop-rspec', '1.30.0'
30
+ gem.add_development_dependency 'rubycritic', '>= 4.0.2'
30
31
  gem.add_development_dependency 'simplecov', '~> 0.16.x'
31
32
  gem.add_development_dependency 'yard', '>= 0.9.18'
32
33
  gem.add_development_dependency 'yardstick', '>= 0.9.9'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Sinclair::ConfigBuilder do
4
+ describe 'yard' do
5
+ describe '#instance_eval' do
6
+ subject(:builder) do
7
+ described_class.new(config, :name)
8
+ end
9
+
10
+ let(:config) { MyConfig.new }
11
+
12
+ it 'sets variable from config' do
13
+ expect { builder.instance_eval { |c| c.name 'John' } }
14
+ .to change(config, :name)
15
+ .from(nil).to('John')
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Sinclair::ConfigFactory do
4
+ describe '#yard' do
5
+ subject(:factory) do
6
+ described_class.new(
7
+ config_class: config_class,
8
+ config_attributes: config_attributes
9
+ )
10
+ end
11
+
12
+ let(:config_class) { Class.new(Sinclair::Config) }
13
+ let(:config_attributes) { [:name] }
14
+ let(:config) { factory.config }
15
+
16
+ describe 'general usage' do
17
+ context 'when not passing any argument' do
18
+ subject(:factory) { described_class.new }
19
+
20
+ before do
21
+ factory.add_configs(:name)
22
+ factory.configure { |c| c.name 'John' }
23
+ end
24
+
25
+ it 'returns an instance of Config child class' do
26
+ expect(config.class.superclass)
27
+ .to eq(Sinclair::Config)
28
+ end
29
+
30
+ it 'configures name to be John' do
31
+ expect(config.name).to eq('John')
32
+ end
33
+
34
+ it 'returns always the same instance' do
35
+ expect(factory.config).to be_equal(config)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '#reset_config' do
41
+ it 'changes config instance' do
42
+ expect { factory.reset_config }
43
+ .to change(factory, :config)
44
+ end
45
+ end
46
+
47
+ describe '#add_configs' do
48
+ let(:config) { factory.config }
49
+
50
+ context 'when it already have config_attributes' do
51
+ it 'returns current possible configurations' do
52
+ expect(factory.add_configs('active'))
53
+ .to eq(%i[name active])
54
+ end
55
+ end
56
+
57
+ context 'when initializing with no parameters' do
58
+ subject(:factory) { described_class.new }
59
+
60
+ it 'adds method to config' do
61
+ expect { factory.add_configs(:active) }
62
+ .to change { config.respond_to?(:active) }
63
+ .from(false).to(true)
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#configure' do
69
+ let(:config_class) { MyConfig }
70
+
71
+ it 'sets variable on config' do
72
+ expect { factory.configure { name 'John' } }
73
+ .to change(config, :name)
74
+ .from(nil).to('John')
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Sinclair::Configurable do
4
+ describe '#yard' do
5
+ before do
6
+ MyConfigurable.configure do
7
+ host 'interstella.com'
8
+ port 5555
9
+ end
10
+ end
11
+
12
+ it 'sets right value for config host' do
13
+ expect(MyConfigurable.config.host)
14
+ .to eq('interstella.com')
15
+ end
16
+
17
+ it 'sets right value for config port' do
18
+ expect(MyConfigurable.config.port)
19
+ .to eq(5555)
20
+ end
21
+
22
+ context 'when reset_config is called' do
23
+ before { MyConfigurable.reset_config }
24
+
25
+ it 'returns initial value for host' do
26
+ expect(MyConfigurable.config.host)
27
+ .to be_nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Sinclair::ConfigBuilder do
4
+ subject(:builder) { described_class.new(config, *config_attributes) }
5
+
6
+ let(:config) { MyConfig.new }
7
+ let(:config_attributes) { [:name] }
8
+
9
+ it 'changes responds to given config' do
10
+ expect(builder).to respond_to(:name)
11
+ end
12
+
13
+ it 'does not respond to othr configs' do
14
+ expect(builder).not_to respond_to(:other_method)
15
+ end
16
+
17
+ it 'responds to other parent methods' do
18
+ expect(builder).to respond_to(:to_s)
19
+ end
20
+
21
+ context 'when builder was configuratd with the method called' do
22
+ let(:config_attributes) { [:name] }
23
+
24
+ it 'sets the instance variable' do
25
+ expect { builder.name 'John' }
26
+ .to change(config, :name)
27
+ .from(nil).to('John')
28
+ end
29
+ end
30
+
31
+ context 'when builder was configuratd without the method called' do
32
+ let(:config_attributes) { [] }
33
+
34
+ it 'does not set the instance variable and raises error' do
35
+ expect { builder.name 'John' }
36
+ .to raise_error(NoMethodError)
37
+ .and not_change(config, :name)
38
+ end
39
+ end
40
+
41
+ context 'when using a variable name from builder variables' do
42
+ let(:config_attributes) { [:config] }
43
+
44
+ it 'sets the instance variable without changing builder instance variable' do
45
+ expect { builder.config(key: 'value') }
46
+ .to not_change { builder.instance_variable_get(:@config) }
47
+ .and change(config, :config)
48
+ .from(nil).to(key: 'value')
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::ConfigFactory do
6
+ subject(:factory) { described_class.new }
7
+
8
+ let(:config) { factory.config }
9
+ let(:other_factory) { described_class.new }
10
+
11
+ describe '#config' do
12
+ it do
13
+ expect(factory.config).to be_a(Sinclair::Config)
14
+ end
15
+
16
+ context 'when calling twice' do
17
+ it 'returns the same instance' do
18
+ expect(factory.config)
19
+ .to be(factory.config)
20
+ end
21
+ end
22
+
23
+ context 'when calling after reset_config' do
24
+ before { factory.reset_config }
25
+
26
+ it do
27
+ expect(factory.config).to be_a(Sinclair::Config)
28
+ end
29
+ end
30
+
31
+ context 'when initializing with custom config class' do
32
+ subject(:factory) { described_class.new(config_class: DummyConfig) }
33
+
34
+ it do
35
+ expect(factory.config).to be_a(DummyConfig)
36
+ end
37
+
38
+ context 'when calling after reset_config' do
39
+ before { factory.reset_config }
40
+
41
+ it do
42
+ expect(factory.config).to be_a(DummyConfig)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#reset_config' do
49
+ let(:old_instance) { factory.config }
50
+
51
+ it 'reset_configs instance' do
52
+ expect { factory.reset_config }
53
+ .to change { factory.config.eql?(old_instance) }
54
+ .from(true).to(false)
55
+ end
56
+
57
+ it 'forces regeneration of instance' do
58
+ expect { factory.reset_config }
59
+ .not_to change { factory.config.class }
60
+ end
61
+
62
+ context 'when initializing with custom config class' do
63
+ subject(:factory) { described_class.new(config_class: DummyConfig) }
64
+
65
+ it 'reset_configs instance' do
66
+ expect { factory.reset_config }
67
+ .to change { factory.config.eql?(old_instance) }
68
+ .from(true).to(false)
69
+ end
70
+
71
+ it 'forces regeneration of instance' do
72
+ expect { factory.reset_config }
73
+ .not_to change { factory.config.class }
74
+ end
75
+
76
+ it 'does not affect other factories' do
77
+ expect { factory.reset_config }
78
+ .not_to change(other_factory, :config)
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#add_configs' do
84
+ it 'adds reader to config' do
85
+ expect { factory.add_configs(:name) }
86
+ .to add_method(:name).to(factory.config)
87
+ end
88
+
89
+ it 'does not add setter to config' do
90
+ expect { factory.add_configs(:name) }
91
+ .not_to add_method(:name=).to(factory.config)
92
+ end
93
+
94
+ it 'does not change Sinclair::Config class' do
95
+ expect { factory.add_configs(:name) }
96
+ .not_to add_method(:name).to(Sinclair::Config.new)
97
+ end
98
+
99
+ it 'allows config_builder to handle method missing' do
100
+ factory.add_configs(:name)
101
+ expect { factory.configure { name 'John' } }.not_to raise_error
102
+ end
103
+
104
+ it 'changes subclasses of config' do
105
+ expect { factory.add_configs(:name) }
106
+ .to add_method(:name).to(factory.child.config)
107
+ end
108
+
109
+ it 'does not mess with parent config_builder' do
110
+ factory.child.add_configs(:name)
111
+ expect { factory.configure { name 'John' } }
112
+ .to raise_error(NoMethodError)
113
+ end
114
+
115
+ context 'when initializing with custom config class' do
116
+ it do
117
+ expect { factory.add_configs(:name) }
118
+ .to add_method(:name).to(factory.config)
119
+ end
120
+
121
+ it 'does not change other config classes' do
122
+ expect { factory.add_configs(:name) }
123
+ .not_to add_method(:name).to(other_factory.config)
124
+ end
125
+ end
126
+
127
+ it 'does not mess with configurable methods' do
128
+ factory.add_configs(:reset_config)
129
+ factory.configure { |c| c.reset_config true }
130
+ factory.reset_config
131
+ expect(factory.config).to be_a(Sinclair::Config)
132
+ end
133
+ end
134
+
135
+ describe '#configure' do
136
+ before { factory.add_configs(:user, 'password') }
137
+
138
+ it do
139
+ expect { factory.configure { |c| c.user 'Bob' } }
140
+ .to change(config, :user)
141
+ .from(nil).to('Bob')
142
+ end
143
+
144
+ context 'when it was defined using string' do
145
+ it do
146
+ expect { factory.configure { |c| c.password '123456' } }
147
+ .to change(config, :password)
148
+ .from(nil).to('123456')
149
+ end
150
+ end
151
+
152
+ context 'when calling a method that was not defined' do
153
+ it do
154
+ expect { factory.configure { |c| c.nope '123456' } }
155
+ .to raise_error(NoMethodError)
156
+ end
157
+ end
158
+ end
159
+
160
+ describe '#child' do
161
+ it { expect(factory.child).to be_a(described_class) }
162
+
163
+ it 'generates factory capable of generating config subclasses' do
164
+ expect(factory.child.config).to be_a(factory.config.class)
165
+ end
166
+
167
+ it 'generates factory that does not generate same config class' do
168
+ expect(factory.child.config.class).not_to eq(factory.config.class)
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::Configurable do
6
+ subject(:configurable) { Class.new(DummyConfigurable) }
7
+
8
+ describe '.config' do
9
+ it do
10
+ expect(configurable.config).to be_a(Sinclair::Config)
11
+ end
12
+
13
+ context 'when calling twice' do
14
+ it 'returns the same instance' do
15
+ expect(configurable.config)
16
+ .to be(configurable.config)
17
+ end
18
+ end
19
+
20
+ context 'when calling after reset_config' do
21
+ before { configurable.reset_config }
22
+
23
+ it do
24
+ expect(configurable.config).to be_a(Sinclair::Config)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '.reset_config' do
30
+ let(:old_instance) { configurable.config }
31
+
32
+ it 'reset_configs instance' do
33
+ expect { configurable.reset_config }
34
+ .to change { configurable.config.eql?(old_instance) }
35
+ .from(true).to(false)
36
+ end
37
+
38
+ it 'forces regeneration of instance' do
39
+ expect { configurable.reset_config }
40
+ .not_to change { configurable.config.class }
41
+ end
42
+ end
43
+
44
+ describe '.configurable_with' do
45
+ it 'adds reader to config' do
46
+ expect { configurable.send(:configurable_with, :name) }
47
+ .to add_method(:name).to(configurable.config)
48
+ end
49
+
50
+ it 'does not add setter to config' do
51
+ expect { configurable.send(:configurable_with, :name) }
52
+ .not_to add_method(:name=).to(configurable.config)
53
+ end
54
+
55
+ it 'does not change parent class configuration' do
56
+ expect { configurable.send(:configurable_with, :name) }
57
+ .not_to add_method(:name).to(DummyConfigurable.config)
58
+ end
59
+
60
+ it 'does not change Sinclair::Config' do
61
+ expect { configurable.send(:configurable_with, :name) }
62
+ .not_to add_method(:name).to(Sinclair::Config.new)
63
+ end
64
+
65
+ it 'does not mess with configurable methods' do
66
+ configurable.send(:configurable_with, :reset_config)
67
+ configurable.configure { |c| c.reset_config true }
68
+ configurable.reset_config
69
+ expect(configurable.config).to be_a(Sinclair::Config)
70
+ end
71
+ end
72
+
73
+ describe '.configure' do
74
+ let(:config) { configurable.config }
75
+
76
+ it do
77
+ expect { configurable.configure { |c| c.user 'Bob' } }
78
+ .to change(config, :user)
79
+ .from(nil).to('Bob')
80
+ end
81
+
82
+ context 'when it was defined using string' do
83
+ it do
84
+ expect { configurable.configure { |c| c.password '123456' } }
85
+ .to change(config, :password)
86
+ .from(nil).to('123456')
87
+ end
88
+ end
89
+
90
+ context 'when calling a method that was not defined' do
91
+ it do
92
+ expect { configurable.configure { |c| c.nope '123456' } }
93
+ .to raise_error(NoMethodError)
94
+ end
95
+ end
96
+ end
97
+ end
data/spec/spec_helper.rb CHANGED
@@ -22,7 +22,6 @@ RSpec.configure do |config|
22
22
 
23
23
  config.order = 'random'
24
24
  config.include Sinclair::Matchers
25
-
26
- config.before do
27
- end
28
25
  end
26
+
27
+ RSpec::Matchers.define_negated_matcher :not_change, :change
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DummyConfig
4
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DummyConfigurable
4
+ extend Sinclair::Configurable
5
+
6
+ configurable_with :user, 'password'
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MyConfig
4
+ attr_reader :name, :config
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MyConfigurable
4
+ extend Sinclair::Configurable
5
+
6
+ configurable_with :host, :port
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinclair
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DarthJee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-30 00:00:00.000000000 Z
11
+ date: 2019-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.30.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubycritic
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 4.0.2
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 4.0.2
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -167,10 +181,15 @@ files:
167
181
  - LICENSE
168
182
  - README.md
169
183
  - Rakefile
184
+ - config/rubycritc.rb
170
185
  - config/yardstick.rb
171
186
  - config/yardstick.yml
172
187
  - docker-compose.yml
173
188
  - lib/sinclair.rb
189
+ - lib/sinclair/config.rb
190
+ - lib/sinclair/config_builder.rb
191
+ - lib/sinclair/config_factory.rb
192
+ - lib/sinclair/configurable.rb
174
193
  - lib/sinclair/matchers.rb
175
194
  - lib/sinclair/matchers/add_method.rb
176
195
  - lib/sinclair/matchers/add_method_to.rb
@@ -178,6 +197,7 @@ files:
178
197
  - lib/sinclair/options_parser.rb
179
198
  - lib/sinclair/version.rb
180
199
  - scripts/check_readme.sh
200
+ - scripts/rubycritic.sh
181
201
  - sinclair.gemspec
182
202
  - sinclair.jpg
183
203
  - spec/integration/readme/my_class_spec.rb
@@ -186,11 +206,17 @@ files:
186
206
  - spec/integration/readme/sinclair_spec.rb
187
207
  - spec/integration/sinclair/matchers_spec.rb
188
208
  - spec/integration/yard/my_builder_spec.rb
209
+ - spec/integration/yard/sinclair/config_builder_spec.rb
210
+ - spec/integration/yard/sinclair/config_factory_spec.rb
211
+ - spec/integration/yard/sinclair/configurable_spec.rb
189
212
  - spec/integration/yard/sinclair/matchers/add_method_spec.rb
190
213
  - spec/integration/yard/sinclair/matchers/add_method_to_spec.rb
191
214
  - spec/integration/yard/sinclair/method_definition_spec.rb
192
215
  - spec/integration/yard/sinclair/options_parser_spec.rb
193
216
  - spec/integration/yard/sinclair_spec.rb
217
+ - spec/lib/sinclair/config_builder_spec.rb
218
+ - spec/lib/sinclair/config_factory_spec.rb
219
+ - spec/lib/sinclair/configurable_spec.rb
194
220
  - spec/lib/sinclair/matchers/add_method_spec.rb
195
221
  - spec/lib/sinclair/matchers/add_method_to_spec.rb
196
222
  - spec/lib/sinclair/matchers_spec.rb
@@ -201,11 +227,15 @@ files:
201
227
  - spec/support/fixture_helpers.rb
202
228
  - spec/support/models/default_value.rb
203
229
  - spec/support/models/dummy_builder.rb
230
+ - spec/support/models/dummy_config.rb
231
+ - spec/support/models/dummy_configurable.rb
204
232
  - spec/support/models/dummy_options_parser.rb
205
233
  - spec/support/models/initial_valuer.rb
206
234
  - spec/support/models/my_builder.rb
207
235
  - spec/support/models/my_class.rb
208
236
  - spec/support/models/my_concern.rb
237
+ - spec/support/models/my_config.rb
238
+ - spec/support/models/my_configurable.rb
209
239
  - spec/support/models/my_model.rb
210
240
  - spec/support/models/person.rb
211
241
  - spec/support/models/purchase.rb