qonfig 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +15 -0
- data/README.md +25 -2
- data/bin/rspec +55 -0
- data/gemfiles/with_external_deps.gemfile +8 -0
- data/gemfiles/without_external_deps.gemfile +5 -0
- data/lib/qonfig/data_set.rb +2 -0
- data/lib/qonfig/dsl.rb +1 -1
- data/lib/qonfig/{exceptions.rb → errors.rb} +10 -0
- data/lib/qonfig/plugins/access_mixin.rb +12 -0
- data/lib/qonfig/plugins/toml/commands/expose_toml.rb +146 -0
- data/lib/qonfig/plugins/toml/commands/load_from_toml.rb +49 -0
- data/lib/qonfig/plugins/toml/data_set.rb +19 -0
- data/lib/qonfig/plugins/toml/dsl.rb +27 -0
- data/lib/qonfig/plugins/toml/loaders/toml.rb +24 -0
- data/lib/qonfig/plugins/toml/tomlrb_fixes.rb +92 -0
- data/lib/qonfig/plugins/toml/uploaders/toml.rb +25 -0
- data/lib/qonfig/plugins/toml.rb +26 -0
- data/lib/qonfig/plugins.rb +1 -0
- data/lib/qonfig/version.rb +1 -1
- data/lib/qonfig.rb +4 -1
- data/qonfig.gemspec +1 -1
- metadata +16 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62b74a92c4c74b79f222e029726296a63b51ba3a57886a00911a34ffbcbced25
|
4
|
+
data.tar.gz: 33fa91631b6554dec3547c9c31faddf805bc4a56becbe7042e1942c19c493f16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 152acb89e834fccaaed1b4bfae379f8263d795b2e4e7b7913f6a2b98fd1bfebf984dec1c82a3568ddc08a3e16fdec2be7783f1f583ef09a3dc6b1386f9afb18f
|
7
|
+
data.tar.gz: c468d5a5c289dc8b4b7b337e62314dbbf9d388b5dd6df1248a14e957a97be9937d7f24c47aa8634ffe415dbd092ed4f3c5b447036770b171fb6d87454eceb4e8
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -3,11 +3,35 @@ matrix:
|
|
3
3
|
fast_finish: true
|
4
4
|
include:
|
5
5
|
- rvm: 2.3.8
|
6
|
+
gemfile: gemfiles/with_external_deps.gemfile
|
7
|
+
env: TEST_PLUGINS=true
|
6
8
|
- rvm: 2.4.6
|
9
|
+
gemfile: gemfiles/with_external_deps.gemfile
|
10
|
+
env: TEST_PLUGINS=true
|
7
11
|
- rvm: 2.5.5
|
12
|
+
gemfile: gemfiles/with_external_deps.gemfile
|
13
|
+
env: TEST_PLUGINS=true
|
8
14
|
- rvm: 2.6.3
|
15
|
+
gemfile: gemfiles/with_external_deps.gemfile
|
16
|
+
env: TEST_PLUGINS=true
|
9
17
|
- rvm: ruby-head
|
18
|
+
gemfile: gemfiles/with_external_deps.gemfile
|
19
|
+
env: TEST_PLUGINS=true
|
10
20
|
- rvm: jruby-head
|
21
|
+
gemfile: gemfiles/with_external_deps.gemfile
|
22
|
+
env: TEST_PLUGINS=true
|
23
|
+
- rvm: 2.3.8
|
24
|
+
gemfile: gemfiles/without_external_deps.gemfile
|
25
|
+
- rvm: 2.4.6
|
26
|
+
gemfile: gemfiles/without_external_deps.gemfile
|
27
|
+
- rvm: 2.5.5
|
28
|
+
gemfile: gemfiles/without_external_deps.gemfile
|
29
|
+
- rvm: 2.6.3
|
30
|
+
gemfile: gemfiles/without_external_deps.gemfile
|
31
|
+
- rvm: ruby-head
|
32
|
+
gemfile: gemfiles/without_external_deps.gemfile
|
33
|
+
- rvm: jruby-head
|
34
|
+
gemfile: gemfiles/without_external_deps.gemfile
|
11
35
|
allow_failures:
|
12
36
|
- rvm: ruby-head
|
13
37
|
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [0.12.0] - 2019-07-19
|
5
|
+
### Added
|
6
|
+
- Support for **TOML** (`.toml`) format
|
7
|
+
- realized as a plugin (`Qonfig.plugin(:toml)`);
|
8
|
+
- provides `#save_to_toml`, `#load_from_toml`, `#expose_toml` methods and works in `#*_yaml`-like manner);
|
9
|
+
- Custom `bin/rspec` command:
|
10
|
+
- `bin/rspec -n` - run tests without plugin tests;
|
11
|
+
- `bin/rspec -w` - run all tests;
|
12
|
+
- Added more convinient aliases for `Qonfig::DataSet` instances:
|
13
|
+
- `#save_to_yaml` => `#dump_to_yaml`;
|
14
|
+
- `#save_to_json` => `#dump_to_json`;
|
15
|
+
- `#save_to_toml` => `#dump_to_toml`;
|
16
|
+
### Changed
|
17
|
+
- Actualized development dependencies;
|
18
|
+
|
4
19
|
## [0.11.0] - 2019-05-15
|
5
20
|
### Added
|
6
21
|
- `#save_to_json` - save configurations to a json file (uses native `::JSON.generate` under the hood);
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ require 'qonfig'
|
|
39
39
|
- [Save to YAML file](#save-to-yaml-file) (`save_to_yaml`)
|
40
40
|
- [Smart Mixin](#smart-mixin) (`Qonfig::Configurable`)
|
41
41
|
- [Plugins](#plugins)
|
42
|
-
|
42
|
+
- [toml](#plugin-toml) (provides `load_from_toml`, `save_to_toml`, `expose_toml`)
|
43
43
|
---
|
44
44
|
|
45
45
|
### Definition and Access
|
@@ -819,7 +819,7 @@ config.save_to_json(path: 'config.json')
|
|
819
819
|
}
|
820
820
|
```
|
821
821
|
|
822
|
-
#### With value preprocessing
|
822
|
+
#### With value preprocessing and custom options
|
823
823
|
|
824
824
|
```ruby
|
825
825
|
class AppConfig < Qonfig::DataSet
|
@@ -1044,6 +1044,29 @@ Qonfig.plugin(:plugin_name) # or Qonfig.plugin('plugin_name')
|
|
1044
1044
|
|
1045
1045
|
---
|
1046
1046
|
|
1047
|
+
### Plugins: toml
|
1048
|
+
|
1049
|
+
- adds support for `toml` format ([specification](https://github.com/toml-lang/toml));
|
1050
|
+
- depends on `toml-rb` gem;
|
1051
|
+
- provides `load_from_toml` (works in `load_from_yaml` manner [doc](#load-from-yaml-file));
|
1052
|
+
- provides `save_to_toml` (works in `save_to_yaml` manner [doc](#save-to-yaml-file)) (`toml-rb` has no native options);
|
1053
|
+
- provides `expose_toml` (works in `expose_yaml` manner [doc](#expose-yaml));
|
1054
|
+
|
1055
|
+
```ruby
|
1056
|
+
require 'toml-rb'
|
1057
|
+
Qonfig.plugin(:toml)
|
1058
|
+
# and use :)
|
1059
|
+
```
|
1060
|
+
---
|
1061
|
+
|
1062
|
+
## Roadmap
|
1063
|
+
|
1064
|
+
- support for TOML format;
|
1065
|
+
- explicit "settings" object;
|
1066
|
+
- validation layer;
|
1067
|
+
- distributed configuration server;
|
1068
|
+
- support for Rails-like secrets;
|
1069
|
+
|
1047
1070
|
## Contributing
|
1048
1071
|
|
1049
1072
|
- Fork it ( https://github.com/0exp/qonfig/fork )
|
data/bin/rspec
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pathname'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
module QonfigSpecRunner
|
8
|
+
extend self
|
9
|
+
|
10
|
+
expand_gemfile_path = lambda do |gemfile_name|
|
11
|
+
File.expand_path(File.join('..', 'gemfiles', gemfile_name), __dir__)
|
12
|
+
end
|
13
|
+
|
14
|
+
GEMFILES = {
|
15
|
+
with_external_deps: expand_gemfile_path.call('with_external_deps.gemfile'),
|
16
|
+
without_external_deps: expand_gemfile_path.call('without_external_deps.gemfile')
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
def run!
|
20
|
+
OptionParser.new do |opts|
|
21
|
+
opts.banner = 'Usage: bin/rspec [options]'
|
22
|
+
|
23
|
+
opts.on(
|
24
|
+
'-w', '--with-plugins',
|
25
|
+
'Run tests with test for plugins'
|
26
|
+
) { run_with_specs_for_plugins! }
|
27
|
+
|
28
|
+
opts.on(
|
29
|
+
'-n', '--without-plugins',
|
30
|
+
'Run tests without tests for plugins'
|
31
|
+
) { run_without_specs_for_plugins! }
|
32
|
+
end.parse!
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def run_with_specs_for_plugins!
|
38
|
+
ENV['TEST_PLUGINS'] = 'true'
|
39
|
+
ENV['BUNDLE_GEMFILE'] = GEMFILES[:with_external_deps]
|
40
|
+
run_tests!
|
41
|
+
end
|
42
|
+
|
43
|
+
def run_without_specs_for_plugins!
|
44
|
+
ENV['BUNDLE_GEMFILE'] = GEMFILES[:without_external_deps]
|
45
|
+
run_tests!
|
46
|
+
end
|
47
|
+
|
48
|
+
def run_tests!
|
49
|
+
require 'rubygems'
|
50
|
+
require 'bundler/setup'
|
51
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
QonfigSpecRunner.run!
|
data/lib/qonfig/data_set.rb
CHANGED
@@ -101,6 +101,7 @@ class Qonfig::DataSet
|
|
101
101
|
Qonfig::Uploaders::JSON.upload(settings, path: path, options: options, &value_processor)
|
102
102
|
end
|
103
103
|
end
|
104
|
+
alias_method :dump_to_json, :save_to_json
|
104
105
|
|
105
106
|
# @option path [String]
|
106
107
|
# @option symbolize_keys [Boolean]
|
@@ -125,6 +126,7 @@ class Qonfig::DataSet
|
|
125
126
|
)
|
126
127
|
end
|
127
128
|
end
|
129
|
+
alias_method :dump_to_yaml, :save_to_yaml
|
128
130
|
|
129
131
|
# @param key [String, Symbol]
|
130
132
|
# @return [Object]
|
data/lib/qonfig/dsl.rb
CHANGED
@@ -9,6 +9,10 @@ module Qonfig
|
|
9
9
|
# @since 0.1.0
|
10
10
|
ArgumentError = Class.new(ArgumentError)
|
11
11
|
|
12
|
+
# @api public
|
13
|
+
# @since 0.12.0
|
14
|
+
PluginError = Class.new(Error)
|
15
|
+
|
12
16
|
# @api public
|
13
17
|
# @since 0.11.0
|
14
18
|
IncorrectHashTransformationError = Class.new(ArgumentError)
|
@@ -98,4 +102,10 @@ module Qonfig
|
|
98
102
|
# @api public
|
99
103
|
# @since 0.7.0
|
100
104
|
ExposeError = Class.new(Error)
|
105
|
+
|
106
|
+
# @see Qonfig::Plugin::TOMLFormat
|
107
|
+
#
|
108
|
+
# @api public
|
109
|
+
# @since 0.12.0
|
110
|
+
UnresolvedPluginDependencyError = Class.new(PluginError)
|
101
111
|
end
|
@@ -23,4 +23,16 @@ module Qonfig::Plugins::AccessMixin
|
|
23
23
|
def plugins
|
24
24
|
Qonfig::Plugins.names
|
25
25
|
end
|
26
|
+
|
27
|
+
# @param plugin_name [String, Symbol]
|
28
|
+
# @param plugin_klass [Class<Qonfig::Plugins::Abstract>]
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @see Qonfig::Plugins
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
# @since 0.12.0
|
35
|
+
def register_plugin(plugin_name, plugin_klass)
|
36
|
+
Qonfig::Plugins.register_plugin(plugin_name, plugin_klass)
|
37
|
+
end
|
26
38
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.12.0
|
5
|
+
class Qonfig::Commands::ExposeTOML < Qonfig::Commands::Base
|
6
|
+
# @return [Hash]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.12.0
|
10
|
+
EXPOSERS = { file_name: :file_name, env_key: :env_key }.freeze
|
11
|
+
|
12
|
+
# @return [Hash]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.12.0
|
16
|
+
EMPTY_TOML_DATA = {}.freeze
|
17
|
+
|
18
|
+
# @return [String]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.12.0
|
22
|
+
attr_reader :file_path
|
23
|
+
|
24
|
+
# @return [Boolean]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.12.0
|
28
|
+
attr_reader :strict
|
29
|
+
|
30
|
+
# @return [Symbol]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
# @since 0.12.0
|
34
|
+
attr_reader :via
|
35
|
+
|
36
|
+
# @return [Symbol, String]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.12.0
|
40
|
+
attr_reader :env
|
41
|
+
|
42
|
+
# @param file_path [String]
|
43
|
+
# @option strict [Boolean]
|
44
|
+
# @option via [Symbol]
|
45
|
+
# @option env [String, Symbol]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.12.0
|
49
|
+
def initialize(file_path, strict: true, via:, env:)
|
50
|
+
unless env.is_a?(Symbol) || env.is_a?(String) || env.is_a?(Numeric)
|
51
|
+
raise Qonfig::ArgumentError, ':env should be a string or a symbol'
|
52
|
+
end
|
53
|
+
|
54
|
+
raise Qonfig::ArgumentError, ':env should be provided' if env.to_s.empty?
|
55
|
+
raise Qonfig::ArgumentError, 'used :via is unsupported' unless EXPOSERS.key?(via)
|
56
|
+
|
57
|
+
@file_path = file_path
|
58
|
+
@strict = strict
|
59
|
+
@via = via
|
60
|
+
@env = env
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param settings [Qonfig::Settings]
|
64
|
+
# @return [void]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
# @since 0.12.0
|
68
|
+
def call(settings)
|
69
|
+
case via
|
70
|
+
when EXPOSERS[:file_name]
|
71
|
+
expose_file_name!(settings)
|
72
|
+
when EXPOSERS[:env_key]
|
73
|
+
expose_env_key!(settings)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# @param settings [Qonfig::Settings]
|
80
|
+
# @return [void]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
# @since 0.12.0
|
84
|
+
# rubocop:disable Metrics/AbcSize
|
85
|
+
def expose_file_name!(settings)
|
86
|
+
# NOTE: transform file name (insert environment name into the file name)
|
87
|
+
# from: path/to/file/file_name.file_extension
|
88
|
+
# to: path/to/file/file_name.env_name.file_extension
|
89
|
+
|
90
|
+
pathname = Pathname.new(file_path)
|
91
|
+
dirname = pathname.dirname
|
92
|
+
extname = pathname.extname.to_s
|
93
|
+
basename = pathname.basename.to_s.sub!(extname, '')
|
94
|
+
envname = [env.to_s, extname].reject(&:empty?).join('')
|
95
|
+
envfile = [basename, envname].reject(&:empty?).join('.')
|
96
|
+
realfile = dirname.join(envfile).to_s
|
97
|
+
|
98
|
+
toml_data = load_toml_data(realfile)
|
99
|
+
toml_based_settings = build_data_set_class(toml_data).new.settings
|
100
|
+
|
101
|
+
settings.__append_settings__(toml_based_settings)
|
102
|
+
end
|
103
|
+
# rubocop:enable Metrics/AbcSize
|
104
|
+
|
105
|
+
# @param settings [Qonfig::Settings]
|
106
|
+
# @return [void]
|
107
|
+
#
|
108
|
+
# @raise [Qonfig::ExposeError]
|
109
|
+
#
|
110
|
+
# @api private
|
111
|
+
# @since 0.12.0
|
112
|
+
# rubocop:disable Metrics/AbcSize
|
113
|
+
def expose_env_key!(settings)
|
114
|
+
toml_data = load_toml_data(file_path)
|
115
|
+
toml_data_slice = toml_data[env] || toml_data[env.to_s] || toml_data[env.to_sym]
|
116
|
+
toml_data_slice = EMPTY_TOML_DATA.dup if toml_data_slice.nil? && !strict
|
117
|
+
|
118
|
+
raise(
|
119
|
+
Qonfig::ExposeError,
|
120
|
+
"#{file_path} file does not contain settings with <#{env}> environment key!"
|
121
|
+
) unless toml_data_slice
|
122
|
+
|
123
|
+
toml_based_settings = build_data_set_class(toml_data_slice).new.settings
|
124
|
+
|
125
|
+
settings.__append_settings__(toml_based_settings)
|
126
|
+
end
|
127
|
+
# rubocop:enable Metrics/AbcSize
|
128
|
+
|
129
|
+
# @param file_path [String]
|
130
|
+
# @return [Hash]
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
# @since 0.12.0
|
134
|
+
def load_toml_data(file_path)
|
135
|
+
Qonfig::Loaders::TOML.load_file(file_path, fail_on_unexist: strict)
|
136
|
+
end
|
137
|
+
|
138
|
+
# @param toml_data [Hash]
|
139
|
+
# @return [Class<Qonfig::DataSet>]
|
140
|
+
#
|
141
|
+
# @api private
|
142
|
+
# @since 0.12.0
|
143
|
+
def build_data_set_class(toml_data)
|
144
|
+
Qonfig::DataSet::ClassBuilder.build_from_hash(toml_data)
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.12.0
|
5
|
+
class Qonfig::Commands::LoadFromTOML < Qonfig::Commands::Base
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.12.0
|
10
|
+
attr_reader :file_path
|
11
|
+
|
12
|
+
# @return [Boolean]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.12.0
|
16
|
+
attr_reader :strict
|
17
|
+
|
18
|
+
# @param file_path [String]
|
19
|
+
# @option strict [Boolean]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.12.0
|
23
|
+
def initialize(file_path, strict: true)
|
24
|
+
@file_path = file_path
|
25
|
+
@strict = strict
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param settings [Qonfig::Settings]
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.12.0
|
33
|
+
def call(settings)
|
34
|
+
toml_data = Qonfig::Loaders::TOML.load_file(file_path, fail_on_unexist: strict)
|
35
|
+
toml_based_settings = build_data_set_class(toml_data).new.settings
|
36
|
+
settings.__append_settings__(toml_based_settings)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @param toml_data [Hash]
|
42
|
+
# @return [Class<Qonfig::DataSet>]
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
# @since 0.12.0
|
46
|
+
def build_data_set_class(toml_data)
|
47
|
+
Qonfig::DataSet::ClassBuilder.build_from_hash(toml_data)
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.12.0
|
5
|
+
class Qonfig::DataSet
|
6
|
+
# @option path [String]
|
7
|
+
# @option options [Hash<Symbol,Any>] Nothing, just for compatability and consistency
|
8
|
+
# @param value_processor [Block]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
# @since 0.12.0
|
13
|
+
def save_to_toml(path:, options: Qonfig::Uploaders::TOML::DEFAULT_OPTIONS, &value_processor)
|
14
|
+
thread_safe_access do
|
15
|
+
Qonfig::Uploaders::TOML.upload(settings, path: path, options: options, &value_processor)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias_method :dump_to_toml, :save_to_toml
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.12.0
|
5
|
+
module Qonfig::DSL
|
6
|
+
# @param file_path [String]
|
7
|
+
# @option strict [Boolean]
|
8
|
+
# @return [void]
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
# @since 0.12.0
|
12
|
+
def load_from_toml(file_path, strict: true)
|
13
|
+
commands << Qonfig::Commands::LoadFromTOML.new(file_path, strict: strict)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param file_path [String]
|
17
|
+
# @option strict [Boolean]
|
18
|
+
# @option via [Symbol]
|
19
|
+
# @option env [Symbol, String]
|
20
|
+
# @return [void]
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
# @since 0.12.0
|
24
|
+
def expose_toml(file_path, strict: true, via:, env:)
|
25
|
+
commands << Qonfig::Commands::ExposeTOML.new(file_path, strict: strict, via: via, env: env)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.12.0
|
5
|
+
class Qonfig::Loaders::TOML < Qonfig::Loaders::Basic
|
6
|
+
class << self
|
7
|
+
# @param data [String]
|
8
|
+
# @return [Object]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.12.0
|
12
|
+
def load(data)
|
13
|
+
::TomlRB.parse(ERB.new(data).result)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Object]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.12.0
|
20
|
+
def load_empty_data
|
21
|
+
::TomlRB.parse('')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE:
|
4
|
+
# - dumper sorts settins keys as a collection of string or symbols only
|
5
|
+
# - settings values like { a: 1, 'b' => 2 } will fail on comparison errors (Symbol with String)
|
6
|
+
# - problem is located in TomlRB::Dumper#sort_pairs(hash) method
|
7
|
+
# - problem code: `hash.keys.sort.map` (failed on `.sort` part)
|
8
|
+
# - we can patch this code by explicit `.map(&:to_s)` before `.sort`
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.12.0
|
12
|
+
module TomlRB::Dumper::SortFixPatch
|
13
|
+
private
|
14
|
+
|
15
|
+
# NOTE: target method for our fix
|
16
|
+
def sort_pairs(hash)
|
17
|
+
nested_pairs = []
|
18
|
+
simple_pairs = []
|
19
|
+
table_array_pairs = []
|
20
|
+
|
21
|
+
# NOTE: our fix (original code: `hash.keys.sort`) (for details see notes above)
|
22
|
+
fixed_keys_sort(hash).each do |key|
|
23
|
+
val = hash[key]
|
24
|
+
element = [key, val]
|
25
|
+
|
26
|
+
if val.is_a? Hash
|
27
|
+
nested_pairs << element
|
28
|
+
elsif val.is_a?(Array) && val.first.is_a?(Hash)
|
29
|
+
table_array_pairs << element
|
30
|
+
else
|
31
|
+
simple_pairs << element
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
[simple_pairs, nested_pairs, table_array_pairs]
|
36
|
+
end
|
37
|
+
|
38
|
+
# NOTE: our fix (for detales see notes above)
|
39
|
+
def fixed_keys_sort(hash)
|
40
|
+
hash.keys.sort_by(&:to_s)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# NOTE:
|
45
|
+
# - dumper uses ultra primitive way to conver objects to toml format
|
46
|
+
# - dumper represents nil values as a simple strings without quots,
|
47
|
+
# but should not represent them at all
|
48
|
+
# - dumper can not validate invalid structures
|
49
|
+
# (for example: [1, [2,3], nil] (invalid, cuz arrays should contain values of one type))
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.12.0
|
53
|
+
module TomlRB::Dumper::ObjectConverterFix
|
54
|
+
private
|
55
|
+
|
56
|
+
# NOTE: target method for our fix
|
57
|
+
def dump_simple_pairs(simple_pairs)
|
58
|
+
simple_pairs.each do |key, val|
|
59
|
+
key = quote_key(key) unless bare_key? key
|
60
|
+
# NOTE: our fix (original code: `@toml_str << "#{key} = #{to_toml(val)}\n"`)
|
61
|
+
fixed_toml_value_append(key, val)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# NOTE: our fix
|
66
|
+
def fixed_toml_value_append(key, val)
|
67
|
+
@toml_str << "#{key} = #{fixed_to_toml(val)}\n" unless val.nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
# NOTE our fix
|
71
|
+
def fixed_to_toml(object)
|
72
|
+
# NOTE: original code of #toml(obj):
|
73
|
+
# if object.is_a? Time
|
74
|
+
# object.strftime('%Y-%m-%dT%H:%M:%SZ')
|
75
|
+
# else
|
76
|
+
# object.inspect
|
77
|
+
# end
|
78
|
+
|
79
|
+
case object
|
80
|
+
when Time, DateTime, Date
|
81
|
+
object.strftime('%Y-%m-%dT%H:%M:%SZ')
|
82
|
+
else
|
83
|
+
# NOTE: validate result value via value parsing before dump
|
84
|
+
object.inspect.tap { |value| ::TomlRB.parse("sample = #{value}") }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @since 0.12.0
|
90
|
+
TomlRB::Dumper.prepend(TomlRB::Dumper::SortFixPatch)
|
91
|
+
# @since 0.12.0
|
92
|
+
TomlRB::Dumper.prepend(TomlRB::Dumper::ObjectConverterFix)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.12.0
|
5
|
+
class Qonfig::Uploaders::TOML < Qonfig::Uploaders::File
|
6
|
+
class << self
|
7
|
+
# @param settings [Qonfig::Settings]
|
8
|
+
# @param options [Hash<Symbol,Any>]
|
9
|
+
# @param value_processor [Block]
|
10
|
+
# @return [String]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.12.0
|
14
|
+
def represent_settings(settings, options, &value_processor)
|
15
|
+
settings_hash =
|
16
|
+
if block_given?
|
17
|
+
settings.__to_hash__(transform_value: value_processor)
|
18
|
+
else
|
19
|
+
settings.__to_hash__
|
20
|
+
end
|
21
|
+
|
22
|
+
::TomlRB.dump(settings_hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.12.0
|
5
|
+
class Qonfig::Plugins::TOML < Qonfig::Plugins::Abstract
|
6
|
+
class << self
|
7
|
+
# @return [void]
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @since 0.12.0
|
11
|
+
def load!
|
12
|
+
raise(
|
13
|
+
Qonfig::UnresolvedPluginDependencyError,
|
14
|
+
'::TomlRB does not exist or "toml-rb" gem is not loaded'
|
15
|
+
) unless const_defined?('::TomlRB')
|
16
|
+
|
17
|
+
require_relative 'toml/tomlrb_fixes'
|
18
|
+
require_relative 'toml/loaders/toml'
|
19
|
+
require_relative 'toml/uploaders/toml'
|
20
|
+
require_relative 'toml/commands/load_from_toml'
|
21
|
+
require_relative 'toml/commands/expose_toml'
|
22
|
+
require_relative 'toml/data_set'
|
23
|
+
require_relative 'toml/dsl'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/qonfig/plugins.rb
CHANGED
data/lib/qonfig/version.rb
CHANGED
data/lib/qonfig.rb
CHANGED
@@ -5,7 +5,7 @@ require 'json'
|
|
5
5
|
require 'erb'
|
6
6
|
|
7
7
|
module Qonfig
|
8
|
-
require_relative 'qonfig/
|
8
|
+
require_relative 'qonfig/errors'
|
9
9
|
require_relative 'qonfig/loaders'
|
10
10
|
require_relative 'qonfig/uploaders'
|
11
11
|
require_relative 'qonfig/commands'
|
@@ -19,4 +19,7 @@ module Qonfig
|
|
19
19
|
# @api public
|
20
20
|
# @since 0.4.0
|
21
21
|
extend Plugins::AccessMixin
|
22
|
+
|
23
|
+
# @since 0.12.0
|
24
|
+
register_plugin('toml', Qonfig::Plugins::TOML)
|
22
25
|
end
|
data/qonfig.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency 'coveralls', '~> 0.8'
|
32
32
|
spec.add_development_dependency 'simplecov', '~> 0.16'
|
33
33
|
spec.add_development_dependency 'rspec', '~> 3.8'
|
34
|
-
spec.add_development_dependency 'armitage-rubocop', '~> 0.
|
34
|
+
spec.add_development_dependency 'armitage-rubocop', '~> 0.73'
|
35
35
|
|
36
36
|
spec.add_development_dependency 'bundler'
|
37
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.
|
4
|
+
version: 0.12.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: 2019-
|
11
|
+
date: 2019-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coveralls
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
61
|
+
version: '0.73'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
68
|
+
version: '0.73'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,7 +129,10 @@ files:
|
|
129
129
|
- README.md
|
130
130
|
- Rakefile
|
131
131
|
- bin/console
|
132
|
+
- bin/rspec
|
132
133
|
- bin/setup
|
134
|
+
- gemfiles/with_external_deps.gemfile
|
135
|
+
- gemfiles/without_external_deps.gemfile
|
133
136
|
- lib/qonfig.rb
|
134
137
|
- lib/qonfig/command_set.rb
|
135
138
|
- lib/qonfig/commands.rb
|
@@ -148,7 +151,7 @@ files:
|
|
148
151
|
- lib/qonfig/data_set/class_builder.rb
|
149
152
|
- lib/qonfig/data_set/validator.rb
|
150
153
|
- lib/qonfig/dsl.rb
|
151
|
-
- lib/qonfig/
|
154
|
+
- lib/qonfig/errors.rb
|
152
155
|
- lib/qonfig/loaders.rb
|
153
156
|
- lib/qonfig/loaders/basic.rb
|
154
157
|
- lib/qonfig/loaders/json.rb
|
@@ -157,6 +160,14 @@ files:
|
|
157
160
|
- lib/qonfig/plugins/abstract.rb
|
158
161
|
- lib/qonfig/plugins/access_mixin.rb
|
159
162
|
- lib/qonfig/plugins/registry.rb
|
163
|
+
- lib/qonfig/plugins/toml.rb
|
164
|
+
- lib/qonfig/plugins/toml/commands/expose_toml.rb
|
165
|
+
- lib/qonfig/plugins/toml/commands/load_from_toml.rb
|
166
|
+
- lib/qonfig/plugins/toml/data_set.rb
|
167
|
+
- lib/qonfig/plugins/toml/dsl.rb
|
168
|
+
- lib/qonfig/plugins/toml/loaders/toml.rb
|
169
|
+
- lib/qonfig/plugins/toml/tomlrb_fixes.rb
|
170
|
+
- lib/qonfig/plugins/toml/uploaders/toml.rb
|
160
171
|
- lib/qonfig/settings.rb
|
161
172
|
- lib/qonfig/settings/builder.rb
|
162
173
|
- lib/qonfig/settings/key_guard.rb
|