qonfig 0.25.0 → 0.26.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 +4 -4
- data/.gitignore +0 -2
- data/.rubocop.yml +19 -1
- data/.travis.yml +7 -2
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +102 -0
- data/README.md +2 -0
- data/gemfiles/with_external_deps.gemfile.lock +112 -0
- data/gemfiles/without_external_deps.gemfile.lock +102 -0
- data/lib/qonfig.rb +1 -1
- data/lib/qonfig/commands/definition/load_from_env.rb +2 -0
- data/lib/qonfig/commands/definition/load_from_env/value_converter.rb +2 -0
- data/lib/qonfig/imports/direct_key.rb +8 -2
- data/lib/qonfig/imports/mappings.rb +8 -2
- data/lib/qonfig/loaders/basic.rb +2 -0
- data/lib/qonfig/loaders/json.rb +2 -1
- data/lib/qonfig/settings.rb +5 -1
- data/lib/qonfig/settings/key_matcher.rb +1 -1
- data/lib/qonfig/uploaders/base.rb +2 -0
- data/lib/qonfig/uploaders/yaml.rb +2 -0
- data/lib/qonfig/version.rb +1 -1
- data/qonfig.gemspec +4 -6
- data/sig/.keep +0 -0
- data/spec/features/clear_options_spec.rb +92 -0
- data/spec/features/compacted_config_spec.rb +308 -0
- data/spec/features/composition_spec.rb +207 -0
- data/spec/features/config_definition_and_representation_spec.rb +535 -0
- data/spec/features/definition_order_spec.rb +69 -0
- data/spec/features/dig_functionality_spec.rb +47 -0
- data/spec/features/dot_notation_spec.rb +159 -0
- data/spec/features/export_settings_spec.rb +138 -0
- data/spec/features/expose_json_spec.rb +281 -0
- data/spec/features/expose_self/format_option_dynamic_spec.rb +69 -0
- data/spec/features/expose_self/format_option_json_spec.rb +74 -0
- data/spec/features/expose_self/format_option_unsupported_spec.rb +27 -0
- data/spec/features/expose_self/format_option_yaml_spec.rb +77 -0
- data/spec/features/expose_self_spec.rb +97 -0
- data/spec/features/expose_yaml_spec.rb +263 -0
- data/spec/features/freeze_state_spec.rb +122 -0
- data/spec/features/get_config_keys_spec.rb +62 -0
- data/spec/features/get_config_values_spec.rb +41 -0
- data/spec/features/has_a_key_spec.rb +48 -0
- data/spec/features/import_settings_spec.rb +323 -0
- data/spec/features/indifferent_access_spec.rb +57 -0
- data/spec/features/inheritance_spec.rb +110 -0
- data/spec/features/instantiation_without_class_definition_spec.rb +59 -0
- data/spec/features/iteration_over_setting_keys_spec.rb +48 -0
- data/spec/features/load_from_env_spec.rb +240 -0
- data/spec/features/load_from_json_spec.rb +97 -0
- data/spec/features/load_from_self/format_option_json_spec.rb +31 -0
- data/spec/features/load_from_self/format_option_unsupported_spec.rb +27 -0
- data/spec/features/load_from_self/format_option_yaml_spec.rb +49 -0
- data/spec/features/load_from_self/with_erb_instructions_spec.rb +33 -0
- data/spec/features/load_from_self/with_hash_like_data_representation_spec.rb +66 -0
- data/spec/features/load_from_self/with_non_hash_like_data_representation_spec.rb +19 -0
- data/spec/features/load_from_self/without_end_data_spec.rb +11 -0
- data/spec/features/load_from_yaml_spec.rb +110 -0
- data/spec/features/load_setting_values_from_file/by_instance_method_examples.rb +171 -0
- data/spec/features/load_setting_values_from_file/by_macros_examples.rb +165 -0
- data/spec/features/load_setting_values_from_file/load_from_json_spec.rb +21 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/end_data_with_env_spec.rb +100 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_end_data_spec.rb +129 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_incorrect_end_data_spec.rb +34 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/without_end_data_spec.rb +65 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/end_data_with_env_spec.rb +94 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_end_data_spec.rb +126 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_incorrect_end_data_spec.rb +32 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/without_end_data_spec.rb +65 -0
- data/spec/features/load_setting_values_from_file/load_from_yaml_spec.rb +21 -0
- data/spec/features/load_setting_values_from_file/shared_behavior_spec.rb +33 -0
- data/spec/features/mixin_spec.rb +387 -0
- data/spec/features/non_redefineable_core_methods_spec.rb +29 -0
- data/spec/features/plugins/pretty_print_spec.rb +86 -0
- data/spec/features/plugins/toml/expose_self/format_option_toml_spec.rb +71 -0
- data/spec/features/plugins/toml/expose_toml_spec.rb +221 -0
- data/spec/features/plugins/toml/load_from_self/format_option_toml_spec.rb +27 -0
- data/spec/features/plugins/toml/load_from_toml_spec.rb +109 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_from_toml_spec.rb +27 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/end_data_with_env_spec.rb +95 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_end_data_spec.rb +125 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_incorrect_end_data_spec.rb +34 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/without_end_data_spec.rb +65 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/shared_behavior_spec.rb +34 -0
- data/spec/features/plugins/toml/save_to_toml_spec.rb +149 -0
- data/spec/features/plugins/vault/expose_vault_spec.rb +117 -0
- data/spec/features/plugins/vault/load_from_vault_spec.rb +80 -0
- data/spec/features/plugins_spec.rb +89 -0
- data/spec/features/reload_spec.rb +75 -0
- data/spec/features/run_code_with_temporary_settings_spec.rb +104 -0
- data/spec/features/save_to_file/save_to_json_spec.rb +157 -0
- data/spec/features/save_to_file/save_to_yaml_spec.rb +189 -0
- data/spec/features/settings_as_predicates_spec.rb +47 -0
- data/spec/features/settings_redefinition_spec.rb +30 -0
- data/spec/features/slice_functionality_spec.rb +69 -0
- data/spec/features/subset_functionality_spec.rb +49 -0
- data/spec/features/validation_spec.rb +916 -0
- data/spec/fixtures/array_settings.yml +3 -0
- data/spec/fixtures/expose_json/incompatible_root_structure.json +6 -0
- data/spec/fixtures/expose_json/incompatible_structure.json +4 -0
- data/spec/fixtures/expose_json/project.development.json +7 -0
- data/spec/fixtures/expose_json/project.json +30 -0
- data/spec/fixtures/expose_json/project.production.json +7 -0
- data/spec/fixtures/expose_json/project.staging.json +7 -0
- data/spec/fixtures/expose_json/project.test.json +7 -0
- data/spec/fixtures/expose_yaml/incompatible_structure.yml +2 -0
- data/spec/fixtures/expose_yaml/project.development.yml +4 -0
- data/spec/fixtures/expose_yaml/project.production.yml +4 -0
- data/spec/fixtures/expose_yaml/project.staging.yml +4 -0
- data/spec/fixtures/expose_yaml/project.test.yml +4 -0
- data/spec/fixtures/expose_yaml/project.yml +25 -0
- data/spec/fixtures/json_array_sample.json +14 -0
- data/spec/fixtures/json_object_sample.json +9 -0
- data/spec/fixtures/json_with_empty_object.json +6 -0
- data/spec/fixtures/json_with_erb.json +6 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.development.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.production.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.staging.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.test.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.toml +27 -0
- data/spec/fixtures/plugins/toml/mini_file.toml +6 -0
- data/spec/fixtures/plugins/toml/toml_sample_with_all_types.toml +72 -0
- data/spec/fixtures/plugins/toml/values_file/with_env.toml +13 -0
- data/spec/fixtures/plugins/toml/values_file/without_env.toml +6 -0
- data/spec/fixtures/rubocop_settings.yml +12 -0
- data/spec/fixtures/shared_settings_with_aliases.yml +10 -0
- data/spec/fixtures/travis_settings.yml +6 -0
- data/spec/fixtures/values_file/with_env.json +19 -0
- data/spec/fixtures/values_file/with_env.yml +17 -0
- data/spec/fixtures/values_file/without_env.json +8 -0
- data/spec/fixtures/values_file/without_env.yml +5 -0
- data/spec/fixtures/with_empty_hash.yml +4 -0
- data/spec/fixtures/with_erb_instructions.yml +3 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/meta_scopes.rb +20 -0
- data/spec/support/spec_support.rb +42 -0
- metadata +128 -11
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe 'Composition' do
|
|
4
|
+
specify 'config composition (multiple inheritance)' do
|
|
5
|
+
class WebAPIConfig < Qonfig::DataSet
|
|
6
|
+
setting :version, '0.1.0'
|
|
7
|
+
setting :header, 'app.vendor'
|
|
8
|
+
setting :strategy do
|
|
9
|
+
setting :format, :json
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class ServerConfig < Qonfig::DataSet
|
|
14
|
+
setting :port, 8080
|
|
15
|
+
setting :host, '0.0.0.0'
|
|
16
|
+
setting :enable_middlewares, true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class DatabaseConfig < Qonfig::DataSet
|
|
20
|
+
setting :username, 'kek'
|
|
21
|
+
setting :password, 'pek'
|
|
22
|
+
setting :connection do
|
|
23
|
+
setting :address, 'google.com'
|
|
24
|
+
setting :port, 12_345
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class ProjectConfig < Qonfig::DataSet
|
|
29
|
+
compose ServerConfig
|
|
30
|
+
|
|
31
|
+
setting :api do
|
|
32
|
+
compose WebAPIConfig
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
setting :db do
|
|
36
|
+
compose DatabaseConfig
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
setting :limits do
|
|
40
|
+
setting :withdraw, 1_000_000
|
|
41
|
+
setting :deposit, 3_000_000
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
config = ProjectConfig.new
|
|
46
|
+
|
|
47
|
+
config.settings.tap do |conf|
|
|
48
|
+
expect(conf.api.version).to eq('0.1.0')
|
|
49
|
+
expect(conf.api.header).to eq('app.vendor')
|
|
50
|
+
expect(conf.api.strategy.format).to eq(:json)
|
|
51
|
+
expect(conf.db.username).to eq('kek')
|
|
52
|
+
expect(conf.db.password).to eq('pek')
|
|
53
|
+
expect(conf.db.connection.address).to eq('google.com')
|
|
54
|
+
expect(conf.db.connection.port).to eq(12_345)
|
|
55
|
+
expect(conf.port).to eq(8080)
|
|
56
|
+
expect(conf.host).to eq('0.0.0.0')
|
|
57
|
+
expect(conf.enable_middlewares).to eq(true)
|
|
58
|
+
expect(conf.limits.withdraw).to eq(1_000_000)
|
|
59
|
+
expect(conf.limits.deposit).to eq(3_000_000)
|
|
60
|
+
|
|
61
|
+
expect(conf[:api][:version]).to eq('0.1.0')
|
|
62
|
+
expect(conf[:api][:header]).to eq('app.vendor')
|
|
63
|
+
expect(conf[:api][:strategy][:format]).to eq(:json)
|
|
64
|
+
expect(conf[:db][:username]).to eq('kek')
|
|
65
|
+
expect(conf[:db][:password]).to eq('pek')
|
|
66
|
+
expect(conf[:db][:connection][:address]).to eq('google.com')
|
|
67
|
+
expect(conf[:db][:connection][:port]).to eq(12_345)
|
|
68
|
+
expect(conf[:port]).to eq(8080)
|
|
69
|
+
expect(conf[:host]).to eq('0.0.0.0')
|
|
70
|
+
expect(conf[:enable_middlewares]).to eq(true)
|
|
71
|
+
expect(conf[:limits][:withdraw]).to eq(1_000_000)
|
|
72
|
+
expect(conf[:limits][:deposit]).to eq(3_000_000)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# hash representation
|
|
76
|
+
expect(config.to_h).to match(
|
|
77
|
+
'db' => {
|
|
78
|
+
'username' => 'kek',
|
|
79
|
+
'password' => 'pek',
|
|
80
|
+
'connection' => {
|
|
81
|
+
'address' => 'google.com',
|
|
82
|
+
'port' => 12_345
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
'port' => 8080,
|
|
86
|
+
'host' => '0.0.0.0',
|
|
87
|
+
'enable_middlewares' => true,
|
|
88
|
+
'limits' => {
|
|
89
|
+
'withdraw' => 1_000_000,
|
|
90
|
+
'deposit' => 3_000_000
|
|
91
|
+
},
|
|
92
|
+
'api' => {
|
|
93
|
+
'version' => '0.1.0',
|
|
94
|
+
'header' => 'app.vendor',
|
|
95
|
+
'strategy' => {
|
|
96
|
+
'format' => :json
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# reconfgure
|
|
102
|
+
config.configure do |conf|
|
|
103
|
+
conf.api.version = '0.2.0'
|
|
104
|
+
conf.api.header = 'app.super.vendor'
|
|
105
|
+
conf.api.strategy.format = :xml
|
|
106
|
+
conf.db.username = 'che'
|
|
107
|
+
conf.db.password = 'burek'
|
|
108
|
+
conf.db.connection.address = 'db.google.com'
|
|
109
|
+
conf.db.connection.port = 666
|
|
110
|
+
conf.port = 8081
|
|
111
|
+
conf.host = 'app.google.com'
|
|
112
|
+
conf.enable_middlewares = false
|
|
113
|
+
conf.limits.withdraw = 0
|
|
114
|
+
conf.limits.deposit = 1_000
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
config.settings.tap do |conf|
|
|
118
|
+
expect(conf.api.version).to eq('0.2.0')
|
|
119
|
+
expect(conf.api.header).to eq('app.super.vendor')
|
|
120
|
+
expect(conf.api.strategy.format).to eq(:xml)
|
|
121
|
+
expect(conf.db.username).to eq('che')
|
|
122
|
+
expect(conf.db.password).to eq('burek')
|
|
123
|
+
expect(conf.db.connection.address).to eq('db.google.com')
|
|
124
|
+
expect(conf.db.connection.port).to eq(666)
|
|
125
|
+
expect(conf.port).to eq(8081)
|
|
126
|
+
expect(conf.host).to eq('app.google.com')
|
|
127
|
+
expect(conf.enable_middlewares).to eq(false)
|
|
128
|
+
expect(conf.limits.withdraw).to eq(0)
|
|
129
|
+
expect(conf.limits.deposit).to eq(1_000)
|
|
130
|
+
|
|
131
|
+
expect(conf[:api][:version]).to eq('0.2.0')
|
|
132
|
+
expect(conf[:api][:header]).to eq('app.super.vendor')
|
|
133
|
+
expect(conf[:api][:strategy][:format]).to eq(:xml)
|
|
134
|
+
expect(conf[:db][:username]).to eq('che')
|
|
135
|
+
expect(conf[:db][:password]).to eq('burek')
|
|
136
|
+
expect(conf[:db][:connection][:address]).to eq('db.google.com')
|
|
137
|
+
expect(conf[:db][:connection][:port]).to eq(666)
|
|
138
|
+
expect(conf[:port]).to eq(8081)
|
|
139
|
+
expect(conf[:host]).to eq('app.google.com')
|
|
140
|
+
expect(conf[:enable_middlewares]).to eq(false)
|
|
141
|
+
expect(conf[:limits][:withdraw]).to eq(0)
|
|
142
|
+
expect(conf[:limits][:deposit]).to eq(1_000)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
expect(config.to_h).to match(
|
|
146
|
+
'db' => {
|
|
147
|
+
'username' => 'che',
|
|
148
|
+
'password' => 'burek',
|
|
149
|
+
'connection' => {
|
|
150
|
+
'address' => 'db.google.com',
|
|
151
|
+
'port' => 666
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
'port' => 8081,
|
|
155
|
+
'host' => 'app.google.com',
|
|
156
|
+
'enable_middlewares' => false,
|
|
157
|
+
'limits' => {
|
|
158
|
+
'withdraw' => 0,
|
|
159
|
+
'deposit' => 1_000
|
|
160
|
+
},
|
|
161
|
+
'api' => {
|
|
162
|
+
'version' => '0.2.0',
|
|
163
|
+
'header' => 'app.super.vendor',
|
|
164
|
+
'strategy' => {
|
|
165
|
+
'format' => :xml
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
specify 'composed config class should be a subtype of Qonfig::DataSet' do
|
|
172
|
+
InappropriateConfig = Class.new
|
|
173
|
+
AppropriateConfig = Class.new(Qonfig::DataSet)
|
|
174
|
+
|
|
175
|
+
expect do
|
|
176
|
+
# (with incompatible config class) on the root
|
|
177
|
+
Class.new(Qonfig::DataSet) do
|
|
178
|
+
compose InappropriateConfig
|
|
179
|
+
end
|
|
180
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
181
|
+
|
|
182
|
+
expect do
|
|
183
|
+
# (with compatible config class) on the root
|
|
184
|
+
Class.new(Qonfig::DataSet) do
|
|
185
|
+
compose AppropriateConfig
|
|
186
|
+
end
|
|
187
|
+
end.not_to raise_error
|
|
188
|
+
|
|
189
|
+
expect do
|
|
190
|
+
# (with incompatible config class) nested
|
|
191
|
+
Class.new(Qonfig::DataSet) do
|
|
192
|
+
setting :nested do
|
|
193
|
+
compose InappropriateConfig
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
197
|
+
|
|
198
|
+
expect do
|
|
199
|
+
# (with compatible config class) nested
|
|
200
|
+
Class.new(Qonfig::DataSet) do
|
|
201
|
+
setting :nested do
|
|
202
|
+
compose AppropriateConfig
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end.not_to raise_error
|
|
206
|
+
end
|
|
207
|
+
end
|
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe 'Config definition and representation' do
|
|
4
|
+
specify 'config object definition, instantiation, settings access and mutation' do
|
|
5
|
+
class SimpleConfig < Qonfig::DataSet
|
|
6
|
+
# setting with nested options
|
|
7
|
+
setting :serializers do
|
|
8
|
+
# :native by default
|
|
9
|
+
setting :json, :native
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# another setting with nested options
|
|
13
|
+
setting :mutations do
|
|
14
|
+
# subsetting
|
|
15
|
+
setting :action do
|
|
16
|
+
# nil by default
|
|
17
|
+
setting :query
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# nested option reopening
|
|
22
|
+
setting :serializers do
|
|
23
|
+
# :native by default
|
|
24
|
+
setting :xml, :native
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
setting :defaults do
|
|
28
|
+
setting :test, false
|
|
29
|
+
end
|
|
30
|
+
# existing nested config redifinition (nested => value)
|
|
31
|
+
setting :defaults, nil
|
|
32
|
+
|
|
33
|
+
setting :shared, true
|
|
34
|
+
# existind setting redifinition (value => nested)
|
|
35
|
+
setting :shared do
|
|
36
|
+
setting :convert, false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# setting without nested options
|
|
40
|
+
setting :steps, 22
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# instantiation
|
|
44
|
+
config = SimpleConfig.new
|
|
45
|
+
|
|
46
|
+
# access via method named as a setting key
|
|
47
|
+
expect(config.settings.serializers.json).to eq(:native)
|
|
48
|
+
expect(config.settings.serializers.xml).to eq(:native)
|
|
49
|
+
expect(config.settings.mutations.action.query).to eq(nil)
|
|
50
|
+
expect(config.settings.steps).to eq(22)
|
|
51
|
+
expect(config.settings.defaults).to eq(nil)
|
|
52
|
+
expect(config.settings.shared.convert).to eq(false)
|
|
53
|
+
|
|
54
|
+
# access via index named as a setting key
|
|
55
|
+
expect(config.settings[:serializers][:json]).to eq(:native)
|
|
56
|
+
expect(config.settings[:serializers][:xml]).to eq(:native)
|
|
57
|
+
expect(config.settings[:mutations][:action][:query]).to eq(nil)
|
|
58
|
+
expect(config.settings[:steps]).to eq(22)
|
|
59
|
+
|
|
60
|
+
# hash representation
|
|
61
|
+
expect(config.to_h).to match(
|
|
62
|
+
'serializers' => {
|
|
63
|
+
'json' => :native,
|
|
64
|
+
'xml' => :native
|
|
65
|
+
},
|
|
66
|
+
'defaults' => nil,
|
|
67
|
+
'shared' => {
|
|
68
|
+
'convert' => false
|
|
69
|
+
},
|
|
70
|
+
'mutations' => {
|
|
71
|
+
'action' => {
|
|
72
|
+
'query' => nil
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
'steps' => 22
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# hash representation (with key transformation)
|
|
79
|
+
expect(config.to_h(key_transformer: proc { |value| value.to_sym })).to match(
|
|
80
|
+
serializers: {
|
|
81
|
+
json: :native,
|
|
82
|
+
xml: :native
|
|
83
|
+
},
|
|
84
|
+
defaults: nil,
|
|
85
|
+
shared: {
|
|
86
|
+
convert: false
|
|
87
|
+
},
|
|
88
|
+
mutations: {
|
|
89
|
+
action: {
|
|
90
|
+
query: nil
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
steps: 22
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# hash representation (with value transformation)
|
|
97
|
+
expect(config.to_h(value_transformer: proc { |value| value.to_s })).to match(
|
|
98
|
+
'serializers' => {
|
|
99
|
+
'json' => 'native',
|
|
100
|
+
'xml' => 'native'
|
|
101
|
+
},
|
|
102
|
+
'defaults' => '',
|
|
103
|
+
'shared' => {
|
|
104
|
+
'convert' => 'false'
|
|
105
|
+
},
|
|
106
|
+
'mutations' => {
|
|
107
|
+
'action' => {
|
|
108
|
+
'query' => ''
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
'steps' => '22'
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# hash representation (with key and value transformations)
|
|
115
|
+
expect(
|
|
116
|
+
config.to_h(
|
|
117
|
+
key_transformer: proc { |value| value.to_sym },
|
|
118
|
+
value_transformer: proc { |value| value.to_s }
|
|
119
|
+
)
|
|
120
|
+
).to match(
|
|
121
|
+
serializers: {
|
|
122
|
+
json: 'native',
|
|
123
|
+
xml: 'native'
|
|
124
|
+
},
|
|
125
|
+
defaults: '',
|
|
126
|
+
shared: {
|
|
127
|
+
convert: 'false'
|
|
128
|
+
},
|
|
129
|
+
mutations: {
|
|
130
|
+
action: {
|
|
131
|
+
query: ''
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
steps: '22'
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# configuration via block (classic style)
|
|
138
|
+
config.configure do |conf|
|
|
139
|
+
conf.serializers.json = :oj
|
|
140
|
+
conf.serializers.xml = :ox
|
|
141
|
+
conf.mutations.action.query = 'select'
|
|
142
|
+
conf.steps = 31
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# access via method named as a setting key
|
|
146
|
+
expect(config.settings.serializers.json).to eq(:oj)
|
|
147
|
+
expect(config.settings.serializers.xml).to eq(:ox)
|
|
148
|
+
expect(config.settings.mutations.action.query).to eq('select')
|
|
149
|
+
expect(config.settings.steps).to eq(31)
|
|
150
|
+
|
|
151
|
+
# access via option index named as a setting key
|
|
152
|
+
expect(config.settings[:serializers][:json]).to eq(:oj)
|
|
153
|
+
expect(config.settings[:serializers][:xml]).to eq(:ox)
|
|
154
|
+
expect(config.settings[:mutations][:action][:query]).to eq('select')
|
|
155
|
+
expect(config.settings[:steps]).to eq(31)
|
|
156
|
+
|
|
157
|
+
# configuration via settings method
|
|
158
|
+
config.settings.serializers.json = 'circular'
|
|
159
|
+
config.settings.serializers.xml = 'angular'
|
|
160
|
+
config.settings.mutations.action.query = :update
|
|
161
|
+
config.settings.steps = nil
|
|
162
|
+
|
|
163
|
+
# access via method named as a setting key
|
|
164
|
+
expect(config.settings.serializers.json).to eq('circular')
|
|
165
|
+
expect(config.settings.serializers.xml).to eq('angular')
|
|
166
|
+
expect(config.settings.mutations.action.query).to eq(:update)
|
|
167
|
+
expect(config.settings.steps).to eq(nil)
|
|
168
|
+
|
|
169
|
+
# access via option index named as a setting key
|
|
170
|
+
expect(config.settings[:serializers][:json]).to eq('circular')
|
|
171
|
+
expect(config.settings[:serializers][:xml]).to eq('angular')
|
|
172
|
+
expect(config.settings[:mutations][:action][:query]).to eq(:update)
|
|
173
|
+
expect(config.settings[:steps]).to eq(nil)
|
|
174
|
+
|
|
175
|
+
# configuration via index accessing
|
|
176
|
+
config.settings[:serializers][:json] = 'pararam'
|
|
177
|
+
config.settings[:serializers][:xml] = 'tratata'
|
|
178
|
+
config.settings[:mutations][:action][:query] = :upsert
|
|
179
|
+
config.settings[:steps] = 1234
|
|
180
|
+
|
|
181
|
+
# access via method named as a setting key
|
|
182
|
+
expect(config.settings.serializers.json).to eq('pararam')
|
|
183
|
+
expect(config.settings.serializers.xml).to eq('tratata')
|
|
184
|
+
expect(config.settings.mutations.action.query).to eq(:upsert)
|
|
185
|
+
expect(config.settings.steps).to eq(1234)
|
|
186
|
+
|
|
187
|
+
# access via option index named as a setting key
|
|
188
|
+
expect(config.settings[:serializers][:json]).to eq('pararam')
|
|
189
|
+
expect(config.settings[:serializers][:xml]).to eq('tratata')
|
|
190
|
+
expect(config.settings[:mutations][:action][:query]).to eq(:upsert)
|
|
191
|
+
expect(config.settings[:steps]).to eq(1234)
|
|
192
|
+
|
|
193
|
+
# instant configuration via proc
|
|
194
|
+
config = SimpleConfig.new do |conf|
|
|
195
|
+
conf.serializers.json = :native
|
|
196
|
+
conf.serializers.xml = :native
|
|
197
|
+
conf.mutations.action.query = 'delete'
|
|
198
|
+
conf.steps = 0
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# access via method named as a setting key
|
|
202
|
+
expect(config.settings.serializers.json).to eq(:native)
|
|
203
|
+
expect(config.settings.serializers.xml).to eq(:native)
|
|
204
|
+
expect(config.settings.mutations.action.query).to eq('delete')
|
|
205
|
+
expect(config.settings.steps).to eq(0)
|
|
206
|
+
|
|
207
|
+
# access via option index named as a setting key
|
|
208
|
+
expect(config.settings[:serializers][:json]).to eq(:native)
|
|
209
|
+
expect(config.settings[:serializers][:xml]).to eq(:native)
|
|
210
|
+
expect(config.settings[:mutations][:action][:query]).to eq('delete')
|
|
211
|
+
expect(config.settings[:steps]).to eq(0)
|
|
212
|
+
|
|
213
|
+
# attempt to get an access to the unexistent setting
|
|
214
|
+
expect { config.settings.deserialization }.to raise_error(Qonfig::UnknownSettingError)
|
|
215
|
+
expect { config.settings.mutations.global }.to raise_error(Qonfig::UnknownSettingError)
|
|
216
|
+
expect { config.settings[:deserialization] }.to raise_error(Qonfig::UnknownSettingError)
|
|
217
|
+
expect { config.settings.mutations[:global] }.to raise_error(Qonfig::UnknownSettingError)
|
|
218
|
+
expect { config.settings.mutations[:global] = 1 }.to raise_error(Qonfig::UnknownSettingError)
|
|
219
|
+
|
|
220
|
+
# access via []-method with indifferent access and dot-notation
|
|
221
|
+
expect(config[:serializers]['json']).to eq(:native)
|
|
222
|
+
expect(config['serializers'][:xml]).to eq(:native)
|
|
223
|
+
expect(config[:mutations][:action][:query]).to eq('delete')
|
|
224
|
+
expect(config['steps']).to eq(0)
|
|
225
|
+
expect(config['serializers.json']).to eq(:native)
|
|
226
|
+
expect(config['serializers.xml']).to eq(:native)
|
|
227
|
+
expect(config['mutations.action.query']).to eq('delete')
|
|
228
|
+
|
|
229
|
+
# configuration via []=-method with/and/without dot-notation
|
|
230
|
+
config['serializers.json'] = :non_native
|
|
231
|
+
config['serializers.xml'] = :non_native
|
|
232
|
+
expect(config['serializers.json']).to eq(:non_native)
|
|
233
|
+
expect(config['serializers.xml']).to eq(:non_native)
|
|
234
|
+
|
|
235
|
+
# mutation of non-existent keys via []=-method fails with error
|
|
236
|
+
expect { config['serializers.toml'] = :native }.to raise_error(Qonfig::UnknownSettingError)
|
|
237
|
+
expect { config['mutations.operation'] = :upgrade }.to raise_error(Qonfig::UnknownSettingError)
|
|
238
|
+
|
|
239
|
+
# ambigous mutation via []=-method fails with corresponding error
|
|
240
|
+
expect do
|
|
241
|
+
config['mutations.action'] = :select
|
|
242
|
+
end.to raise_error(Qonfig::AmbiguousSettingValueError)
|
|
243
|
+
|
|
244
|
+
# hash representation
|
|
245
|
+
expect(config.to_h).to match(
|
|
246
|
+
'serializers' => {
|
|
247
|
+
'json' => :non_native,
|
|
248
|
+
'xml' => :non_native
|
|
249
|
+
},
|
|
250
|
+
'defaults' => nil,
|
|
251
|
+
'shared' => {
|
|
252
|
+
'convert' => false
|
|
253
|
+
},
|
|
254
|
+
'mutations' => {
|
|
255
|
+
'action' => {
|
|
256
|
+
'query' => 'delete'
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
'steps' => 0
|
|
260
|
+
)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
specify 'configuration via hash / hash + proc (instant and not)' do
|
|
264
|
+
class HashConfigurableConfig < Qonfig::DataSet
|
|
265
|
+
setting :a do
|
|
266
|
+
setting :b
|
|
267
|
+
setting :c
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
setting :d
|
|
271
|
+
setting :e
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# configure by hash (via .new)
|
|
275
|
+
config = HashConfigurableConfig.new(
|
|
276
|
+
a: {
|
|
277
|
+
b: { g: 33 },
|
|
278
|
+
c: 2
|
|
279
|
+
},
|
|
280
|
+
d: 33,
|
|
281
|
+
e: { f: 49 }
|
|
282
|
+
)
|
|
283
|
+
expect(config.to_h).to match(
|
|
284
|
+
'a' => {
|
|
285
|
+
'b' => { g: 33 },
|
|
286
|
+
'c' => 2
|
|
287
|
+
},
|
|
288
|
+
'd' => 33,
|
|
289
|
+
'e' => { f: 49 }
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# configure by hash (via #configure)
|
|
293
|
+
config = HashConfigurableConfig.new
|
|
294
|
+
config.configure(
|
|
295
|
+
a: {
|
|
296
|
+
b: 'test',
|
|
297
|
+
c: 'no_test'
|
|
298
|
+
},
|
|
299
|
+
d: 100_500,
|
|
300
|
+
e: false
|
|
301
|
+
)
|
|
302
|
+
expect(config.to_h).to match(
|
|
303
|
+
'a' => {
|
|
304
|
+
'b' => 'test',
|
|
305
|
+
'c' => 'no_test'
|
|
306
|
+
},
|
|
307
|
+
'd' => 100_500,
|
|
308
|
+
'e' => false
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# mixed: configure by hash + proc (via .new)
|
|
312
|
+
config = HashConfigurableConfig.new(d: false, e: true) do |conf|
|
|
313
|
+
conf.a.b = 123
|
|
314
|
+
conf.a.c = 456
|
|
315
|
+
end
|
|
316
|
+
expect(config.to_h).to match(
|
|
317
|
+
'a' => {
|
|
318
|
+
'b' => 123,
|
|
319
|
+
'c' => 456
|
|
320
|
+
},
|
|
321
|
+
'd' => false,
|
|
322
|
+
'e' => true
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# mixed: configure by hash + proc (via #configure)
|
|
326
|
+
config = HashConfigurableConfig.new
|
|
327
|
+
config.configure(a: { b: { c: 49 }, c: 55 }) do |conf|
|
|
328
|
+
conf.d = 0.55
|
|
329
|
+
conf.e = false
|
|
330
|
+
end
|
|
331
|
+
expect(config.to_h).to match(
|
|
332
|
+
'a' => {
|
|
333
|
+
'b' => { c: 49 },
|
|
334
|
+
'c' => 55
|
|
335
|
+
},
|
|
336
|
+
'd' => 0.55,
|
|
337
|
+
'e' => false
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
# proc has higher priority
|
|
341
|
+
config = HashConfigurableConfig.new(a: { b: 1, c: 2 }, d: 3, e: 4) do |conf|
|
|
342
|
+
conf.a.b = 5
|
|
343
|
+
conf.a.c = 6
|
|
344
|
+
conf.d = 7
|
|
345
|
+
conf.e = 8
|
|
346
|
+
end
|
|
347
|
+
expect(config.to_h).to match(
|
|
348
|
+
'a' => {
|
|
349
|
+
'b' => 5,
|
|
350
|
+
'c' => 6
|
|
351
|
+
},
|
|
352
|
+
'd' => 7,
|
|
353
|
+
'e' => 8
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
expect do
|
|
357
|
+
# nonexistent nested key
|
|
358
|
+
HashConfigurableConfig.new(a: { e: 55 })
|
|
359
|
+
end.to raise_error(Qonfig::UnknownSettingError)
|
|
360
|
+
expect do
|
|
361
|
+
# nonexistend nested key + proc
|
|
362
|
+
HashConfigurableConfig.new(a: { e: 55 }) { |conf| conf.d = 'test' }
|
|
363
|
+
end.to raise_error(Qonfig::UnknownSettingError)
|
|
364
|
+
|
|
365
|
+
expect do
|
|
366
|
+
# nonexistent root key
|
|
367
|
+
HashConfigurableConfig.new(g: 'test')
|
|
368
|
+
end.to raise_error(Qonfig::UnknownSettingError)
|
|
369
|
+
expect do
|
|
370
|
+
# nonexistent root key + proc
|
|
371
|
+
HashConfigurableConfig.new(g: 'test') { |conf| conf.e = false }
|
|
372
|
+
end.to raise_error(Qonfig::UnknownSettingError)
|
|
373
|
+
|
|
374
|
+
expect do
|
|
375
|
+
# attempt to override nested settings
|
|
376
|
+
HashConfigurableConfig.new(a: 100)
|
|
377
|
+
end.to raise_error(Qonfig::AmbiguousSettingValueError)
|
|
378
|
+
expect do
|
|
379
|
+
# attempt to override nested settings (+ proc)
|
|
380
|
+
HashConfigurableConfig.new(a: 100) { |conf| conf.a.b = :none }
|
|
381
|
+
end.to raise_error(Qonfig::AmbiguousSettingValueError)
|
|
382
|
+
|
|
383
|
+
# attempt to use non-hash object
|
|
384
|
+
[1, 1.0, Object.new, true, false, Class.new, Module.new, (proc {}), (-> {})].each do |non_hash|
|
|
385
|
+
expect do
|
|
386
|
+
# without proc
|
|
387
|
+
HashConfigurableConfig.new(non_hash)
|
|
388
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
389
|
+
|
|
390
|
+
expect do
|
|
391
|
+
# with valid proc
|
|
392
|
+
HashConfigurableConfig.new(non_hash) { |conf| conf.d = 55 }
|
|
393
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
specify '(#to_h): key (and value) transformer should be a type of Proc' do
|
|
398
|
+
empty_config = Class.new(Qonfig::DataSet).new
|
|
399
|
+
|
|
400
|
+
expect do
|
|
401
|
+
empty_config.to_h(key_transformer: 123)
|
|
402
|
+
end.to raise_error(Qonfig::IncorrectKeyTransformerError)
|
|
403
|
+
|
|
404
|
+
expect do
|
|
405
|
+
empty_config.to_h(value_transformer: 123)
|
|
406
|
+
end.to raise_error(Qonfig::IncorrectValueTransformerError)
|
|
407
|
+
|
|
408
|
+
expect do
|
|
409
|
+
empty_config.to_h(key_transformer: proc {}, value_transformer: 123)
|
|
410
|
+
end.to raise_error(Qonfig::IncorrectValueTransformerError)
|
|
411
|
+
|
|
412
|
+
expect do
|
|
413
|
+
empty_config.to_h(key_transformer: 123, value_transformer: proc {})
|
|
414
|
+
end.to raise_error(Qonfig::IncorrectKeyTransformerError)
|
|
415
|
+
|
|
416
|
+
expect do
|
|
417
|
+
empty_config.to_h(key_transformer: 123, value_transformer: 123)
|
|
418
|
+
end.to raise_error(Qonfig::IncorrectHashTransformationError)
|
|
419
|
+
|
|
420
|
+
expect do
|
|
421
|
+
empty_config.to_h(key_transformer: proc {}, value_transformer: proc {})
|
|
422
|
+
end.not_to raise_error
|
|
423
|
+
|
|
424
|
+
expect do
|
|
425
|
+
empty_config.to_h(key_transformer: proc {})
|
|
426
|
+
end.not_to raise_error
|
|
427
|
+
|
|
428
|
+
expect do
|
|
429
|
+
empty_config.to_h(value_transformer: proc {})
|
|
430
|
+
end.not_to raise_error
|
|
431
|
+
|
|
432
|
+
expect do
|
|
433
|
+
empty_config.to_h
|
|
434
|
+
end.not_to raise_error
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
specify 'only string and symbol keys are supported' do
|
|
438
|
+
[1, 1.0, Object.new, true, false, Class.new, Module.new, (proc {}), (-> {})].each do |key|
|
|
439
|
+
expect do
|
|
440
|
+
Class.new(Qonfig::DataSet) { setting(key) }
|
|
441
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
expect do
|
|
445
|
+
Class.new(Qonfig::DataSet) do
|
|
446
|
+
setting :a
|
|
447
|
+
setting 'b'
|
|
448
|
+
end
|
|
449
|
+
end.not_to raise_error
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
specify 'causes an error when tries to assign a setting value to an option ' \
|
|
453
|
+
'which already have another nested options' do
|
|
454
|
+
class WithNestedOptionsConfig < Qonfig::DataSet
|
|
455
|
+
setting :database do
|
|
456
|
+
setting :hostname, 'localhost'
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
config = WithNestedOptionsConfig.new
|
|
461
|
+
|
|
462
|
+
expect do
|
|
463
|
+
config.configure { |conf| conf.database = double }
|
|
464
|
+
end.to raise_error(Qonfig::AmbiguousSettingValueError)
|
|
465
|
+
|
|
466
|
+
expect do
|
|
467
|
+
config.configure { |conf| conf[:database] = double }
|
|
468
|
+
end.to raise_error(Qonfig::AmbiguousSettingValueError)
|
|
469
|
+
|
|
470
|
+
expect do
|
|
471
|
+
config.configure { |conf| conf[:database][:hostname] = double }
|
|
472
|
+
end.not_to raise_error
|
|
473
|
+
|
|
474
|
+
expect do
|
|
475
|
+
config.configure { |conf| conf.database.hostname = double }
|
|
476
|
+
end.not_to raise_error
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
specify 'fails when tries to use a non-string/non-symbol value as a setting key' do
|
|
480
|
+
incorrect_key_values = [123, Object.new, 15.1, (proc {}), Class.new, true, false]
|
|
481
|
+
correct_key_values = ['test', :test]
|
|
482
|
+
|
|
483
|
+
incorrect_key_values.each do |incorrect_key|
|
|
484
|
+
# check root
|
|
485
|
+
expect do
|
|
486
|
+
Class.new(Qonfig::DataSet) { setting incorrect_key }
|
|
487
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
488
|
+
|
|
489
|
+
# check nested
|
|
490
|
+
expect do
|
|
491
|
+
Class.new(Qonfig::DataSet) do
|
|
492
|
+
setting incorrect_key do
|
|
493
|
+
setting :any
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
497
|
+
|
|
498
|
+
# check nested
|
|
499
|
+
expect do
|
|
500
|
+
Class.new(Qonfig::DataSet) do
|
|
501
|
+
setting :any do
|
|
502
|
+
setting incorrect_key
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
end.to raise_error(Qonfig::ArgumentError)
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
correct_key_values.each do |correct_key|
|
|
509
|
+
# check root
|
|
510
|
+
expect do
|
|
511
|
+
Class.new(Qonfig::DataSet) do
|
|
512
|
+
setting correct_key
|
|
513
|
+
end
|
|
514
|
+
end.not_to raise_error
|
|
515
|
+
|
|
516
|
+
# check nested
|
|
517
|
+
expect do
|
|
518
|
+
Class.new(Qonfig::DataSet) do
|
|
519
|
+
setting correct_key do
|
|
520
|
+
setting :any
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end.not_to raise_error
|
|
524
|
+
|
|
525
|
+
# check nested do
|
|
526
|
+
expect do
|
|
527
|
+
Class.new(Qonfig::DataSet) do
|
|
528
|
+
setting :any do
|
|
529
|
+
setting correct_key
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
end.not_to raise_error
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
end
|