sinclair 1.2.1 → 1.3.0

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