qonfig 0.6.0 → 0.7.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: 05d98b03ee4891914d9701ee98e6965d523f0b75b84d8c5d8aafc6e0d1efdcf0
4
- data.tar.gz: 493e96ebeb18d92870a538d21b68f6b79905f719433e8ba201345e60f4d6317f
3
+ metadata.gz: 508503230a1e21322689d23c7e0bd68c1f3bd3e268719f3b7adcdb1e5595926e
4
+ data.tar.gz: efc18abe1dce63006df0de913a1b1969d1fc36b4e80353985a3126f6b86a9c16
5
5
  SHA512:
6
- metadata.gz: 013cf27437a8434c3b9ba5750ca0a9483479e224bc35244cf8d76d53e712e47c120a22e14e44ed15b0092f1d89a5e41c9d26aee47e16d2edc32ce3f1543a26da
7
- data.tar.gz: fa6498dd72113cde54b22659dfad3d8ae5a092a34d4f1b9efb4d004a5f89c2d1470abe5eef81fd5bd86e9d0a8fde5036670ea41ce76b468e6fa5090c5f787565
6
+ metadata.gz: 5f507d2ef122bdd22258972c6630fd1e8f384d39476e3eb751a2131a505e8fedaae44140deaedac26bbba735854482207da89f80bc862bab4f10b739f547ade3
7
+ data.tar.gz: 7160203dbfd9613b78032307dcd3f1f5bcbb00d0751a0bfbea3621b8fd9e1b645aa6e3783ba790918bba49f9151426b6e17fbdc252ce5da191e7232d2d7ed193
@@ -2,9 +2,9 @@ language: ruby
2
2
  matrix:
3
3
  fast_finish: true
4
4
  include:
5
- - rvm: 2.3.7
6
- - rvm: 2.4.4
7
- - rvm: 2.5.1
5
+ - rvm: 2.3.8
6
+ - rvm: 2.4.5
7
+ - rvm: 2.5.3
8
8
  - rvm: ruby-head
9
9
  - rvm: jruby-head
10
10
  allow_failures:
@@ -1,6 +1,11 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.7.0] - 2018-10-20
5
+ ### Added
6
+ - `expose_yaml` - a command that provides an ability to define config settings
7
+ by loading them from a yaml file where the concrete settings depends on the chosen environment;
8
+
4
9
  ## [0.6.0] - 2018-08-22
5
10
  ### Added
6
11
  - `#shared_config` - instance method that provides an access to the class level config
data/README.md CHANGED
@@ -31,6 +31,7 @@ require 'qonfig'
31
31
  - [State freeze](#state-freeze)
32
32
  - [Settings as Predicates](#settings-as-predicates)
33
33
  - [Load from YAML file](#load-from-yaml-file)
34
+ - [Expose YAML](#expose-yaml) (`Rails`-like environment-based YAML configs)
34
35
  - [Load from JSON file](#load-from-json-file)
35
36
  - [Load from ENV](#load-from-env)
36
37
  - [Load from \_\_END\_\_](#load-from-__end__) (aka `load_from_self`)
@@ -407,12 +408,14 @@ config.settings.database.engine.driver? # => true (true => true)
407
408
 
408
409
  ### Load from YAML file
409
410
 
411
+ - supports `ERB`;
410
412
  - `:strict` mode (fail behaviour when the required yaml file doesnt exist):
411
413
  - `true` (by default) - causes `Qonfig::FileNotFoundError`;
412
414
  - `false` - do nothing, ignore current command;
413
415
 
414
416
  ```yaml
415
- <!-- travis.yml -->
417
+ # travis.yml
418
+
416
419
  sudo: false
417
420
  language: ruby
418
421
  rvm:
@@ -421,14 +424,16 @@ rvm:
421
424
  ```
422
425
 
423
426
  ```yaml
424
- <!-- project.yml -->
427
+ # project.yml
428
+
425
429
  enable_api: false
426
430
  Sidekiq/Scheduler:
427
431
  enable: true
428
432
  ```
429
433
 
430
434
  ```yaml
431
- <!-- ruby_data.yml -->
435
+ # ruby_data.yml
436
+
432
437
  version: <%= RUBY_VERSION %>
433
438
  platform: <%= RUBY_PLATFORM %>
434
439
  ```
@@ -483,6 +488,110 @@ Config.new.to_h # => { "nonexistent_yaml" => {}, "another_key" => nil }
483
488
 
484
489
  ---
485
490
 
491
+ ### Expose YAML
492
+
493
+ - load configurations from YAML file in Rails-like manner (with environments);
494
+ - works in `load_from_yaml` manner;
495
+ - `via:` - how an environment will be determined:
496
+ - `:file_name`
497
+ - load configuration from YAML file that have an `:env` part in it's name;
498
+ - `:env_key`
499
+ - load configuration from YAML file;
500
+ - concrete configuration should be defined in the root key with `:env` name;
501
+ - `env:` - your environment name (must be a type of `String`, `Symbol` or `Numeric`);
502
+ - `strict:` - requires the existence of the file and/or key with the name of the used environment:
503
+ - `true`:
504
+ - file should exist;
505
+ - root key with `:env` name should exist (if `via: :env_key` is used);
506
+ - raises `Qonfig::ExposeError` if file does not contain the required env key (if `via: :env` key is used);
507
+ - raises `Qonfig::FileNotFoundError` if the required file does not exist;
508
+ - `false`:
509
+ - file is not required;
510
+ - root key with `:env` name is not required (if `via: :env_key` is used);
511
+
512
+ #### Environment is defined as a root key of YAML file
513
+
514
+ ```yaml
515
+ # config/project.yml
516
+
517
+ default: &default
518
+ enable_api_mode: true
519
+ google_key: 12345
520
+ window:
521
+ width: 100
522
+ height: 100
523
+
524
+ development:
525
+ <<: *default
526
+
527
+ test:
528
+ <<: *default
529
+ sidekiq_instrumentation: false
530
+
531
+ staging:
532
+ <<: *default
533
+ google_key: 777
534
+ enable_api_mode: false
535
+
536
+ production:
537
+ google_key: asd1-39sd-55aI-O92x
538
+ enable_api_mode: true
539
+ window:
540
+ width: 50
541
+ height: 150
542
+ ```
543
+
544
+ ```ruby
545
+ class Config < Qonfig::DataSet
546
+ expose_yaml 'config/project.yml', via: :env_key, env: :production # load from production env
547
+
548
+ # NOTE: in rails-like application you can use this:
549
+ expose_yaml 'config/project.yml', via: :env_key, env: Rails.env
550
+ end
551
+
552
+ config = Config.new
553
+
554
+ config.settings.enable_api_mode # => true (from :production subset of keys)
555
+ config.settings.google_key # => asd1-39sd-55aI-O92x (from :production subset of keys)
556
+ config.settings.window.width # => 50 (from :production subset of keys)
557
+ config.settings.window.height # => 150 (from :production subset of keys)
558
+ ```
559
+
560
+ #### Environment is defined as a part of YAML file name
561
+
562
+ ```yaml
563
+ # config/sidekiq.staging.yml
564
+
565
+ web:
566
+ username: staging_admin
567
+ password: staging_password
568
+ ```
569
+
570
+ ```yaml
571
+ # config/sidekiq.production.yml
572
+
573
+ web:
574
+ username: urj1o2
575
+ password: u192jd0ixz0
576
+ ```
577
+
578
+ ```ruby
579
+ class SidekiqConfig < Qonfig::DataSet
580
+ # NOTE: file name should be described WITHOUT environment part (in file name attribute)
581
+ expose_yaml 'config/sidekiq.yml', via: :file_name, env: :staging # load from staging env
582
+
583
+ # NOTE: in rails-like application you can use this:
584
+ expose_yaml 'config/sidekiq.yml', via: :file_name, env: Rails.env
585
+ end
586
+
587
+ config = SidekiqConfig.new
588
+
589
+ config.settings.web.username # => staging_admin (from sidekiq.staging.yml)
590
+ config.settings.web.password # => staging_password (from sidekiq.staging.yml)
591
+ ```
592
+
593
+ ---
594
+
486
595
  ### Load from JSON file
487
596
 
488
597
  - `:strict` mode (fail behaviour when the required yaml file doesnt exist):
@@ -490,7 +599,8 @@ Config.new.to_h # => { "nonexistent_yaml" => {}, "another_key" => nil }
490
599
  - `false` - do nothing, ignore current command;
491
600
 
492
601
  ```json
493
- <!-- options.json -->
602
+ // options.json
603
+
494
604
  {
495
605
  "user": "0exp",
496
606
  "password": 12345,
data/Rakefile CHANGED
@@ -2,7 +2,17 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
+ require 'rubocop'
6
+ require 'rubocop-rspec'
7
+ require 'rubocop/rake_task'
5
8
 
6
- RSpec::Core::RakeTask.new(:spec)
9
+ RuboCop::RakeTask.new(:rubocop) do |t|
10
+ config_path = File.expand_path(File.join('.rubocop.yml'), __dir__)
7
11
 
8
- task default: :spec
12
+ t.options = ['--config', config_path]
13
+ t.requires << 'rubocop-rspec'
14
+ end
15
+
16
+ RSpec::Core::RakeTask.new(:rspec)
17
+
18
+ task default: :rspec
@@ -18,6 +18,7 @@ module Qonfig
18
18
  require_relative 'qonfig/commands/load_from_self'
19
19
  require_relative 'qonfig/commands/load_from_env'
20
20
  require_relative 'qonfig/commands/load_from_env/value_converter'
21
+ require_relative 'qonfig/commands/expose_yaml'
21
22
  require_relative 'qonfig/command_set'
22
23
  require_relative 'qonfig/settings'
23
24
  require_relative 'qonfig/settings/lock'
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Qonfig
4
+ module Commands
5
+ # @api private
6
+ # @since 0.7.0
7
+ class ExposeYAML < Base
8
+ # @return [Hash]
9
+ #
10
+ # @api private
11
+ # @since 0.7.0
12
+ EXPOSERS = { file_name: :file_name, env_key: :env_key }.freeze
13
+
14
+ # @return [Hash]
15
+ #
16
+ # @api private
17
+ # @since 0.7.0
18
+ EMPTY_YAML_DATA = {}.freeze
19
+
20
+ # @return [String]
21
+ #
22
+ # @api private
23
+ # @since 0.7.0
24
+ attr_reader :file_path
25
+
26
+ # @return [Boolean]
27
+ #
28
+ # @api private
29
+ # @since 0.7.0
30
+ attr_reader :strict
31
+
32
+ # @return [Symbol]
33
+ #
34
+ # @api private
35
+ # @since 0.7.0
36
+ attr_reader :via
37
+
38
+ # @return [Symbol, String]
39
+ #
40
+ # @api private
41
+ # @since 0.7.0
42
+ attr_reader :env
43
+
44
+ # @param file_path [String]
45
+ # @option strict [Boolean]
46
+ # @option via [Symbol]
47
+ # @option env [String, Symbol]
48
+ #
49
+ # @api private
50
+ # @since 0.7.0
51
+ def initialize(file_path, strict: true, via:, env:)
52
+ unless env.is_a?(Symbol) || env.is_a?(String) || env.is_a?(Numeric)
53
+ raise Qonfig::ArgumentError, ':env should be a string or a symbol'
54
+ end
55
+
56
+ raise Qonfig::ArgumentError, ':env should be provided' if env.to_s.empty?
57
+ raise Qonfig::ArgumentError, 'used :via is unsupported' unless EXPOSERS.key?(via)
58
+
59
+ @file_path = file_path
60
+ @strict = strict
61
+ @via = via
62
+ @env = env
63
+ end
64
+
65
+ # @param settings [Qonfig::Settings]
66
+ # @return [void]
67
+ #
68
+ # @api private
69
+ # @since 0.7.0
70
+ def call(settings)
71
+ case via
72
+ when EXPOSERS[:file_name]
73
+ expose_file_name!(settings)
74
+ when EXPOSERS[:env_key]
75
+ expose_env_key!(settings)
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ # @param settings [Qonfig::Settings]
82
+ # @return [void]
83
+ #
84
+ # @api private
85
+ # @since 0.7.0
86
+ # rubocop:disable Metrics/AbcSize
87
+ def expose_file_name!(settings)
88
+ # NOTE: transform file name (insert environment name into the file name)
89
+ # from: path/to/file/file_name.file_extension
90
+ # to: path/to/file/file_name.env_name.file_extension
91
+
92
+ pathname = Pathname.new(file_path)
93
+ dirname = pathname.dirname
94
+ extname = pathname.extname.to_s
95
+ basename = pathname.basename.to_s.sub!(extname, '')
96
+ envname = [env.to_s, extname].reject(&:empty?).join('')
97
+ envfile = [basename, envname].reject(&:empty?).join('.')
98
+ realfile = dirname.join(envfile).to_s
99
+
100
+ yaml_data = load_yaml_data(realfile)
101
+ yaml_based_settings = build_data_set_class(yaml_data).new.settings
102
+
103
+ settings.__append_settings__(yaml_based_settings)
104
+ end
105
+ # rubocop:enable Metrics/AbcSize
106
+
107
+ # @param settings [Qonfig::Settings]
108
+ # @return [void]
109
+ #
110
+ # @raise [Qonfig::ExposeError]
111
+ # @raise [Qonfig::IncompatibleYAMLStructureError]
112
+ #
113
+ # @api private
114
+ # @since 0.7.0
115
+ # rubocop:disable Metrics/AbcSize
116
+ def expose_env_key!(settings)
117
+ yaml_data = load_yaml_data(file_path)
118
+ yaml_data_slice = yaml_data[env] || yaml_data[env.to_s] || yaml_data[env.to_sym]
119
+ yaml_data_slice = EMPTY_YAML_DATA.dup if yaml_data_slice.nil? && !strict
120
+
121
+ raise(
122
+ Qonfig::ExposeError,
123
+ "#{file_path} file does not contain settings with <#{env}> environment key!"
124
+ ) unless yaml_data_slice
125
+
126
+ raise(
127
+ Qonfig::IncompatibleYAMLStructureError,
128
+ 'YAML content should have a hash-like structure'
129
+ ) unless yaml_data_slice.is_a?(Hash)
130
+
131
+ yaml_based_settings = build_data_set_class(yaml_data_slice).new.settings
132
+
133
+ settings.__append_settings__(yaml_based_settings)
134
+ end
135
+ # rubocop:enable Metrics/AbcSize
136
+
137
+ # @param file_path [String]
138
+ # @return [Hash]
139
+ #
140
+ # @raise [Qonfig::IncompatibleYAMLStructureError]
141
+ #
142
+ # @api private
143
+ # @since 0.7.0
144
+ def load_yaml_data(file_path)
145
+ Qonfig::Loaders::YAML.load_file(file_path, fail_on_unexist: strict).tap do |yaml_data|
146
+ raise(
147
+ Qonfig::IncompatibleYAMLStructureError,
148
+ 'YAML content should have a hash-like structure'
149
+ ) unless yaml_data.is_a?(Hash)
150
+ end
151
+ end
152
+
153
+ # @param yaml_data [Hash]
154
+ # @return [Class<Qonfig::DataSet>]
155
+ #
156
+ # @api private
157
+ # @since 0.7.0
158
+ def build_data_set_class(yaml_data)
159
+ Qonfig::DataSet::ClassBuilder.build_from_hash(yaml_data)
160
+ end
161
+ end
162
+ end
163
+ end
@@ -108,5 +108,17 @@ module Qonfig
108
108
  def load_from_json(file_path, strict: true)
109
109
  commands << Qonfig::Commands::LoadFromJSON.new(file_path, strict: strict)
110
110
  end
111
+
112
+ # @param file_path [String]
113
+ # @option strict [Boolean]
114
+ # @option via [Symbol]
115
+ # @option env [Symbol, String]
116
+ # @return [void]
117
+ #
118
+ # @api public
119
+ # @since 0.7.0
120
+ def expose_yaml(file_path, strict: true, via:, env:)
121
+ commands << Qonfig::Commands::ExposeYAML.new(file_path, strict: strict, via: via, env: env)
122
+ end
111
123
  end
112
124
  end
@@ -80,4 +80,10 @@ module Qonfig
80
80
  # @api public
81
81
  # @since 0.4.0
82
82
  UnregisteredPluginError = Class.new(Error)
83
+
84
+ # @see Qonfig::Commands::ExposeYAML
85
+ #
86
+ # @api public
87
+ # @since 0.7.0
88
+ ExposeError = Class.new(Error)
83
89
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Qonfig
4
+ # @return [String]
5
+ #
4
6
  # @api public
5
7
  # @since 0.1.0
6
- VERSION = '0.6.0'
8
+ VERSION = '0.7.0'
7
9
  end
@@ -29,10 +29,9 @@ Gem::Specification.new do |spec|
29
29
  end
30
30
 
31
31
  spec.add_development_dependency 'coveralls', '~> 0.8'
32
- spec.add_development_dependency 'simplecov', '~> 0.14'
33
- spec.add_development_dependency 'simplecov-json', '~> 0.2'
32
+ spec.add_development_dependency 'simplecov', '~> 0.16'
34
33
  spec.add_development_dependency 'rspec', '~> 3.8'
35
- spec.add_development_dependency 'armitage-rubocop', '~> 0.6'
34
+ spec.add_development_dependency 'armitage-rubocop', '~> 0.10'
36
35
 
37
36
  spec.add_development_dependency 'bundler'
38
37
  spec.add_development_dependency 'rake'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qonfig
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rustam Ibragimov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-22 00:00:00.000000000 Z
11
+ date: 2018-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -30,28 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.14'
33
+ version: '0.16'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.14'
41
- - !ruby/object:Gem::Dependency
42
- name: simplecov-json
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.2'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.2'
40
+ version: '0.16'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rspec
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +58,14 @@ dependencies:
72
58
  requirements:
73
59
  - - "~>"
74
60
  - !ruby/object:Gem::Version
75
- version: '0.6'
61
+ version: '0.10'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
66
  - - "~>"
81
67
  - !ruby/object:Gem::Version
82
- version: '0.6'
68
+ version: '0.10'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: bundler
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +136,7 @@ files:
150
136
  - lib/qonfig/commands/add_option.rb
151
137
  - lib/qonfig/commands/base.rb
152
138
  - lib/qonfig/commands/compose.rb
139
+ - lib/qonfig/commands/expose_yaml.rb
153
140
  - lib/qonfig/commands/load_from_env.rb
154
141
  - lib/qonfig/commands/load_from_env/value_converter.rb
155
142
  - lib/qonfig/commands/load_from_json.rb