qonfig 0.6.0 → 0.7.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: 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