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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.rubocop.yml +19 -1
  4. data/.travis.yml +7 -2
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile.lock +102 -0
  7. data/README.md +2 -0
  8. data/gemfiles/with_external_deps.gemfile.lock +112 -0
  9. data/gemfiles/without_external_deps.gemfile.lock +102 -0
  10. data/lib/qonfig.rb +1 -1
  11. data/lib/qonfig/commands/definition/load_from_env.rb +2 -0
  12. data/lib/qonfig/commands/definition/load_from_env/value_converter.rb +2 -0
  13. data/lib/qonfig/imports/direct_key.rb +8 -2
  14. data/lib/qonfig/imports/mappings.rb +8 -2
  15. data/lib/qonfig/loaders/basic.rb +2 -0
  16. data/lib/qonfig/loaders/json.rb +2 -1
  17. data/lib/qonfig/settings.rb +5 -1
  18. data/lib/qonfig/settings/key_matcher.rb +1 -1
  19. data/lib/qonfig/uploaders/base.rb +2 -0
  20. data/lib/qonfig/uploaders/yaml.rb +2 -0
  21. data/lib/qonfig/version.rb +1 -1
  22. data/qonfig.gemspec +4 -6
  23. data/sig/.keep +0 -0
  24. data/spec/features/clear_options_spec.rb +92 -0
  25. data/spec/features/compacted_config_spec.rb +308 -0
  26. data/spec/features/composition_spec.rb +207 -0
  27. data/spec/features/config_definition_and_representation_spec.rb +535 -0
  28. data/spec/features/definition_order_spec.rb +69 -0
  29. data/spec/features/dig_functionality_spec.rb +47 -0
  30. data/spec/features/dot_notation_spec.rb +159 -0
  31. data/spec/features/export_settings_spec.rb +138 -0
  32. data/spec/features/expose_json_spec.rb +281 -0
  33. data/spec/features/expose_self/format_option_dynamic_spec.rb +69 -0
  34. data/spec/features/expose_self/format_option_json_spec.rb +74 -0
  35. data/spec/features/expose_self/format_option_unsupported_spec.rb +27 -0
  36. data/spec/features/expose_self/format_option_yaml_spec.rb +77 -0
  37. data/spec/features/expose_self_spec.rb +97 -0
  38. data/spec/features/expose_yaml_spec.rb +263 -0
  39. data/spec/features/freeze_state_spec.rb +122 -0
  40. data/spec/features/get_config_keys_spec.rb +62 -0
  41. data/spec/features/get_config_values_spec.rb +41 -0
  42. data/spec/features/has_a_key_spec.rb +48 -0
  43. data/spec/features/import_settings_spec.rb +323 -0
  44. data/spec/features/indifferent_access_spec.rb +57 -0
  45. data/spec/features/inheritance_spec.rb +110 -0
  46. data/spec/features/instantiation_without_class_definition_spec.rb +59 -0
  47. data/spec/features/iteration_over_setting_keys_spec.rb +48 -0
  48. data/spec/features/load_from_env_spec.rb +240 -0
  49. data/spec/features/load_from_json_spec.rb +97 -0
  50. data/spec/features/load_from_self/format_option_json_spec.rb +31 -0
  51. data/spec/features/load_from_self/format_option_unsupported_spec.rb +27 -0
  52. data/spec/features/load_from_self/format_option_yaml_spec.rb +49 -0
  53. data/spec/features/load_from_self/with_erb_instructions_spec.rb +33 -0
  54. data/spec/features/load_from_self/with_hash_like_data_representation_spec.rb +66 -0
  55. data/spec/features/load_from_self/with_non_hash_like_data_representation_spec.rb +19 -0
  56. data/spec/features/load_from_self/without_end_data_spec.rb +11 -0
  57. data/spec/features/load_from_yaml_spec.rb +110 -0
  58. data/spec/features/load_setting_values_from_file/by_instance_method_examples.rb +171 -0
  59. data/spec/features/load_setting_values_from_file/by_macros_examples.rb +165 -0
  60. data/spec/features/load_setting_values_from_file/load_from_json_spec.rb +21 -0
  61. data/spec/features/load_setting_values_from_file/load_from_self/json_format/end_data_with_env_spec.rb +100 -0
  62. data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_end_data_spec.rb +129 -0
  63. data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_incorrect_end_data_spec.rb +34 -0
  64. data/spec/features/load_setting_values_from_file/load_from_self/json_format/without_end_data_spec.rb +65 -0
  65. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/end_data_with_env_spec.rb +94 -0
  66. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_end_data_spec.rb +126 -0
  67. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_incorrect_end_data_spec.rb +32 -0
  68. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/without_end_data_spec.rb +65 -0
  69. data/spec/features/load_setting_values_from_file/load_from_yaml_spec.rb +21 -0
  70. data/spec/features/load_setting_values_from_file/shared_behavior_spec.rb +33 -0
  71. data/spec/features/mixin_spec.rb +387 -0
  72. data/spec/features/non_redefineable_core_methods_spec.rb +29 -0
  73. data/spec/features/plugins/pretty_print_spec.rb +86 -0
  74. data/spec/features/plugins/toml/expose_self/format_option_toml_spec.rb +71 -0
  75. data/spec/features/plugins/toml/expose_toml_spec.rb +221 -0
  76. data/spec/features/plugins/toml/load_from_self/format_option_toml_spec.rb +27 -0
  77. data/spec/features/plugins/toml/load_from_toml_spec.rb +109 -0
  78. data/spec/features/plugins/toml/load_setting_values_from_file/load_from_toml_spec.rb +27 -0
  79. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/end_data_with_env_spec.rb +95 -0
  80. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_end_data_spec.rb +125 -0
  81. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_incorrect_end_data_spec.rb +34 -0
  82. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/without_end_data_spec.rb +65 -0
  83. data/spec/features/plugins/toml/load_setting_values_from_file/shared_behavior_spec.rb +34 -0
  84. data/spec/features/plugins/toml/save_to_toml_spec.rb +149 -0
  85. data/spec/features/plugins/vault/expose_vault_spec.rb +117 -0
  86. data/spec/features/plugins/vault/load_from_vault_spec.rb +80 -0
  87. data/spec/features/plugins_spec.rb +89 -0
  88. data/spec/features/reload_spec.rb +75 -0
  89. data/spec/features/run_code_with_temporary_settings_spec.rb +104 -0
  90. data/spec/features/save_to_file/save_to_json_spec.rb +157 -0
  91. data/spec/features/save_to_file/save_to_yaml_spec.rb +189 -0
  92. data/spec/features/settings_as_predicates_spec.rb +47 -0
  93. data/spec/features/settings_redefinition_spec.rb +30 -0
  94. data/spec/features/slice_functionality_spec.rb +69 -0
  95. data/spec/features/subset_functionality_spec.rb +49 -0
  96. data/spec/features/validation_spec.rb +916 -0
  97. data/spec/fixtures/array_settings.yml +3 -0
  98. data/spec/fixtures/expose_json/incompatible_root_structure.json +6 -0
  99. data/spec/fixtures/expose_json/incompatible_structure.json +4 -0
  100. data/spec/fixtures/expose_json/project.development.json +7 -0
  101. data/spec/fixtures/expose_json/project.json +30 -0
  102. data/spec/fixtures/expose_json/project.production.json +7 -0
  103. data/spec/fixtures/expose_json/project.staging.json +7 -0
  104. data/spec/fixtures/expose_json/project.test.json +7 -0
  105. data/spec/fixtures/expose_yaml/incompatible_structure.yml +2 -0
  106. data/spec/fixtures/expose_yaml/project.development.yml +4 -0
  107. data/spec/fixtures/expose_yaml/project.production.yml +4 -0
  108. data/spec/fixtures/expose_yaml/project.staging.yml +4 -0
  109. data/spec/fixtures/expose_yaml/project.test.yml +4 -0
  110. data/spec/fixtures/expose_yaml/project.yml +25 -0
  111. data/spec/fixtures/json_array_sample.json +14 -0
  112. data/spec/fixtures/json_object_sample.json +9 -0
  113. data/spec/fixtures/json_with_empty_object.json +6 -0
  114. data/spec/fixtures/json_with_erb.json +6 -0
  115. data/spec/fixtures/plugins/toml/expose_toml/project.development.toml +4 -0
  116. data/spec/fixtures/plugins/toml/expose_toml/project.production.toml +4 -0
  117. data/spec/fixtures/plugins/toml/expose_toml/project.staging.toml +4 -0
  118. data/spec/fixtures/plugins/toml/expose_toml/project.test.toml +4 -0
  119. data/spec/fixtures/plugins/toml/expose_toml/project.toml +27 -0
  120. data/spec/fixtures/plugins/toml/mini_file.toml +6 -0
  121. data/spec/fixtures/plugins/toml/toml_sample_with_all_types.toml +72 -0
  122. data/spec/fixtures/plugins/toml/values_file/with_env.toml +13 -0
  123. data/spec/fixtures/plugins/toml/values_file/without_env.toml +6 -0
  124. data/spec/fixtures/rubocop_settings.yml +12 -0
  125. data/spec/fixtures/shared_settings_with_aliases.yml +10 -0
  126. data/spec/fixtures/travis_settings.yml +6 -0
  127. data/spec/fixtures/values_file/with_env.json +19 -0
  128. data/spec/fixtures/values_file/with_env.yml +17 -0
  129. data/spec/fixtures/values_file/without_env.json +8 -0
  130. data/spec/fixtures/values_file/without_env.yml +5 -0
  131. data/spec/fixtures/with_empty_hash.yml +4 -0
  132. data/spec/fixtures/with_erb_instructions.yml +3 -0
  133. data/spec/spec_helper.rb +27 -0
  134. data/spec/support/meta_scopes.rb +20 -0
  135. data/spec/support/spec_support.rb +42 -0
  136. metadata +128 -11
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.2.0
5
+ # rubocop:disable Style/RedundantFreeze, Performance/MethodObjectAsBlock
5
6
  module Qonfig::Commands::Definition::LoadFromENV::ValueConverter
6
7
  # @return [Regexp]
7
8
  #
@@ -80,3 +81,4 @@ module Qonfig::Commands::Definition::LoadFromENV::ValueConverter
80
81
  end
81
82
  end
82
83
  end
84
+ # rubocop:enable Style/RedundantFreeze, Performance/MethodObjectAsBlock
@@ -34,7 +34,10 @@ class Qonfig::Imports::DirectKey < Qonfig::Imports::Abstract
34
34
  # @api private
35
35
  # @since 0.18.0
36
36
  # @version 0.21.0
37
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
37
+ # rubocop:disable Metrics/AbcSize
38
+ # rubocop:disable Metrics/MethodLength
39
+ # rubocop:disable Metrics/BlockLength
40
+ # rubocop:disable Metrics/PerceivedComplexity
38
41
  def import!(settings_interface = Module.new)
39
42
  key_matchers.each do |key_matcher|
40
43
  raise(
@@ -80,7 +83,10 @@ class Qonfig::Imports::DirectKey < Qonfig::Imports::Abstract
80
83
  end
81
84
  end
82
85
  end
83
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
86
+ # rubocop:enable Metrics/AbcSize
87
+ # rubocop:enable Metrics/MethodLength
88
+ # rubocop:enable Metrics/BlockLength
89
+ # rubocop:enable Metrics/PerceivedComplexity
84
90
 
85
91
  private
86
92
 
@@ -40,7 +40,10 @@ class Qonfig::Imports::Mappings < Qonfig::Imports::Abstract
40
40
  # @api private
41
41
  # @since 0.18.0
42
42
  # @version 0.21.0
43
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
43
+ # rubocop:disable Metrics/AbcSize
44
+ # rubocop:disable Metrics/MethodLength
45
+ # rubocop:disable Metrics/BlockLength
46
+ # rubocop:disable Metrics/PerceivedComplexity
44
47
  def import!(settings_interface = Module.new) # rubocop:disable Metrics/AbcSize
45
48
  key_matchers.each_pair do |(mapped_method_name, key_matcher)|
46
49
  raise(
@@ -85,7 +88,10 @@ class Qonfig::Imports::Mappings < Qonfig::Imports::Abstract
85
88
  end
86
89
  end
87
90
  end
88
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
91
+ # rubocop:enable Metrics/AbcSize
92
+ # rubocop:enable Metrics/MethodLength
93
+ # rubocop:enable Metrics/BlockLength
94
+ # rubocop:enable Metrics/PerceivedComplexity
89
95
 
90
96
  private
91
97
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.2.0
5
+ # rubocop:disable Style/StaticClass
5
6
  class Qonfig::Loaders::Basic
6
7
  class << self
7
8
  # @param data [String]
@@ -36,3 +37,4 @@ class Qonfig::Loaders::Basic
36
37
  end
37
38
  end
38
39
  end
40
+ # rubocop:enable Style/StaticClass
@@ -11,8 +11,9 @@ class Qonfig::Loaders::JSON < Qonfig::Loaders::Basic
11
11
  #
12
12
  # @api private
13
13
  # @since 0.5.0
14
+ # @version 0.26.0
14
15
  def load(data)
15
- ::JSON.parse(data, max_nesting: false, allow_nan: true)
16
+ ::JSON.parse(ERB.new(data).result, max_nesting: false, allow_nan: true)
16
17
  rescue ::JSON::ParserError => error
17
18
  raise(Qonfig::JSONLoaderParseError.new(error.message).tap do |exception|
18
19
  exception.set_backtrace(error.backtrace)
@@ -100,6 +100,7 @@ class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_M
100
100
 
101
101
  __prevent_core_method_intersection__(key)
102
102
 
103
+ # rubocop:disable Lint/DuplicateBranch
103
104
  case
104
105
  when with_redefinition || !__options__.key?(key)
105
106
  __options__[key] = value
@@ -108,6 +109,7 @@ class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_M
108
109
  else
109
110
  __options__[key] = value
110
111
  end
112
+ # rubocop:enable Lint/DuplicateBranch
111
113
 
112
114
  __define_option_reader__(key)
113
115
  __define_option_writer__(key)
@@ -622,6 +624,7 @@ class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_M
622
624
  #
623
625
  # @api private
624
626
  # @since 0.9.0
627
+ # rubocop:disable Metrics/AbcSize
625
628
  def __deep_slice__(*keys)
626
629
  {}.tap do |result|
627
630
  begin
@@ -642,6 +645,7 @@ class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_M
642
645
  end
643
646
  end
644
647
  end
648
+ # rubocop:enable Metrics/AbcSize
645
649
 
646
650
  # @param keys [Array<Symbol, String>]
647
651
  # @return [Hash]
@@ -685,7 +689,7 @@ class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_M
685
689
  # TODO: support for patterns
686
690
  __indifferently_accessable_option_key__(key_set)
687
691
  when Array
688
- key_set.map(&method(:__indifferently_accessable_option_key__))
692
+ key_set.map { |key| __indifferently_accessable_option_key__(key) }
689
693
  else
690
694
  raise(
691
695
  Qonfig::ArgumentError,
@@ -181,6 +181,6 @@ class Qonfig::Settings::KeyMatcher
181
181
 
182
182
  regexp_string = strip_regexp_string(regexp_string, left: true, right: true)
183
183
 
184
- Regexp.new('\A' + regexp_string + '\z')
184
+ Regexp.new("\\A#{regexp_string}\\z")
185
185
  end
186
186
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.11.0
5
+ # rubocop:disable Style/StaticClass
5
6
  class Qonfig::Uploaders::Base
6
7
  class << self
7
8
  # @param settings [Qonfig::Settings]
@@ -16,3 +17,4 @@ class Qonfig::Uploaders::Base
16
17
  end
17
18
  end
18
19
  end
20
+ # rubocop:enable Style/StaticClass
@@ -60,6 +60,7 @@ class Qonfig::Uploaders::YAML < Qonfig::Uploaders::File
60
60
  def hash_representation_options(options, &value_processor)
61
61
  {}.tap do |representation_opts|
62
62
  # NOTE: this case/when with the same logic is only used for better code readbility
63
+ # rubocop:disable Lint/DuplicateBranch
63
64
  case
64
65
  # NOTE: options has :symbolize_keys key
65
66
  when options.key?(:symbolize_keys) && !!options[:symbolize_keys]
@@ -70,6 +71,7 @@ class Qonfig::Uploaders::YAML < Qonfig::Uploaders::File
70
71
  representation_opts[:transform_key] = KEY_SYMBOLIZER
71
72
  # :nocov:
72
73
  end
74
+ # rubocop:enable Lint/DuplicateBranch
73
75
 
74
76
  # NOTE: provide value transformer
75
77
  if block_given?
@@ -5,5 +5,5 @@ module Qonfig
5
5
  #
6
6
  # @api public
7
7
  # @since 0.1.0
8
- VERSION = '0.25.0'
8
+ VERSION = '0.26.0'
9
9
  end
data/qonfig.gemspec CHANGED
@@ -25,13 +25,11 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ['lib']
27
27
 
28
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
29
- f.match(%r{^(test|spec|features)/})
30
- end
28
+ spec.files = `git ls-files -z`.split("\x0")
31
29
 
32
- spec.add_development_dependency 'simplecov', '~> 0.19'
33
- spec.add_development_dependency 'rspec', '~> 3.9'
34
- spec.add_development_dependency 'armitage-rubocop', '~> 0.89'
30
+ spec.add_development_dependency 'simplecov', '~> 0.20'
31
+ spec.add_development_dependency 'rspec', '~> 3.10'
32
+ spec.add_development_dependency 'armitage-rubocop', '~> 1.7'
35
33
 
36
34
  spec.add_development_dependency 'bundler'
37
35
  spec.add_development_dependency 'rake', '>= 13'
data/sig/.keep ADDED
File without changes
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Clear options' do
4
+ specify '#clear - sets all options to nil' do
5
+ ENV['QONFIG_CLEAR_GENERIC_OPTION'] = 'true'
6
+ ENV['QONFIG_CLEAR_MEGA_SECRET_VALUE'] = '100500'
7
+
8
+ class SimplifiedConfig < Qonfig::DataSet
9
+ setting :a do
10
+ setting :b do
11
+ setting :c, 55
12
+ end
13
+ end
14
+
15
+ load_from_env prefix: 'QONFIG_CLEAR'
16
+ end
17
+
18
+ class CleansedConfig < Qonfig::DataSet
19
+ setting :database do
20
+ setting :user, '0exp'
21
+ setting :password, 'test123'
22
+ end
23
+
24
+ setting :travis do
25
+ load_from_yaml SpecSupport.fixture_path('travis_settings.yml')
26
+ end
27
+
28
+ setting :self_data do
29
+ load_from_self
30
+ end
31
+
32
+ setting :env_data do
33
+ load_from_env convert_values: true, prefix: /\AQONFIG_CLEAR.*\z/i
34
+ end
35
+
36
+ setting :composed do
37
+ compose SimplifiedConfig
38
+ end
39
+ end
40
+
41
+ config = CleansedConfig.new
42
+
43
+ config.clear!
44
+
45
+ expect(config[:database][:user]).to eq(nil)
46
+ expect(config[:database][:password]).to eq(nil)
47
+ expect(config[:travis][:sudo]).to eq(nil)
48
+ expect(config[:travis][:language]).to eq(nil)
49
+ expect(config[:travis][:rvm]).to eq(nil)
50
+ expect(config[:self_data][:secret_key]).to eq(nil)
51
+ expect(config[:self_data][:api_host]).to eq(nil)
52
+ expect(config[:self_data][:connection_timeout][:seconds]).to eq(nil)
53
+ expect(config[:self_data][:connection_timeout][:enabled]).to eq(nil)
54
+ expect(config[:env_data][:QONFIG_CLEAR_GENERIC_OPTION]).to eq(nil)
55
+ expect(config[:env_data][:QONFIG_CLEAR_MEGA_SECRET_VALUE]).to eq(nil)
56
+ expect(config[:composed][:a][:b][:c]).to eq(nil)
57
+
58
+ expect(config.to_h).to match(
59
+ 'database' => { 'user' => nil, 'password' => nil },
60
+ 'travis' => {
61
+ 'sudo' => nil,
62
+ 'language' => nil,
63
+ 'rvm' => nil
64
+ },
65
+ 'self_data' => {
66
+ 'secret_key' => nil,
67
+ 'api_host' => nil,
68
+ 'connection_timeout' => {
69
+ 'seconds' => nil,
70
+ 'enabled' => nil
71
+ }
72
+ },
73
+ 'env_data' => {
74
+ 'QONFIG_CLEAR_GENERIC_OPTION' => nil,
75
+ 'QONFIG_CLEAR_MEGA_SECRET_VALUE' => nil
76
+ },
77
+ 'composed' => {
78
+ 'a' => { 'b' => { 'c' => nil } },
79
+ 'QONFIG_CLEAR_GENERIC_OPTION' => nil,
80
+ 'QONFIG_CLEAR_MEGA_SECRET_VALUE' => nil
81
+ }
82
+ )
83
+ end
84
+ end
85
+
86
+ __END__
87
+
88
+ secret_key: top-mega-secret
89
+ api_host: super.puper-google.com
90
+ :connection_timeout:
91
+ seconds: 10
92
+ enabled: false
@@ -0,0 +1,308 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Compacted config' do
4
+ describe 'definition and settings access' do
5
+ specify 'constructor without dataset builds compacted config from config\'s class commands' do
6
+ class CompactedCommandsCheck < Qonfig::Compacted
7
+ setting :test, true
8
+ setting :db do
9
+ setting :creds do
10
+ setting :user, '0exp'
11
+ setting :password, 'test123'
12
+ end
13
+ end
14
+
15
+ validate :test, :boolean
16
+ validate 'db.creds.*', :string
17
+ end
18
+
19
+ compacted_config = CompactedCommandsCheck.new
20
+
21
+ # NOTE: check readers
22
+ expect(compacted_config.test).to eq(true)
23
+ expect(compacted_config.db.creds.user).to eq('0exp')
24
+ expect(compacted_config.db.creds.password).to eq('test123')
25
+ # and dot-notation:
26
+ expect(compacted_config[:test]).to eq(true)
27
+ expect(compacted_config['db.creds.user']).to eq('0exp')
28
+ expect(compacted_config['db.creds.password']).to eq('test123')
29
+
30
+ # NOTE: check writers
31
+ compacted_config.test = false
32
+ compacted_config.db.creds.user = 'D@iVeR'
33
+ # and dot-notation:
34
+ compacted_config['db.creds.password'] = 'atata123'
35
+
36
+ # NOTE: check new values
37
+ expect(compacted_config.test).to eq(false)
38
+ expect(compacted_config.db.creds.user).to eq('D@iVeR')
39
+ expect(compacted_config.db.creds.password).to eq('atata123')
40
+
41
+ # NOTE: check validators
42
+ expect { compacted_config.test = 123 }.to raise_error(Qonfig::ValidationError)
43
+ expect { compacted_config.db.creds.user = 123 }.to raise_error(Qonfig::ValidationError)
44
+ expect { compacted_config['db.creds.password'] = 123 }.to raise_error(Qonfig::ValidationError)
45
+ end
46
+
47
+ specify 'support for predicates' do
48
+ class PredicateCheckForCompactedConfig < Qonfig::Compacted
49
+ setting :enabled, true
50
+ setting :queue do
51
+ setting :engine, nil
52
+ setting :workers_count, 10
53
+ end
54
+ end
55
+
56
+ config = PredicateCheckForCompactedConfig.new
57
+
58
+ expect(config.enabled?).to eq(true)
59
+ expect(config.queue?).to eq(true)
60
+ expect(config.queue.engine?).to eq(false)
61
+ expect(config.queue.workers_count?).to eq(true)
62
+
63
+ config.enabled = nil
64
+ config.queue.engine = :sidekiq
65
+
66
+ expect(config.enabled?).to eq(false)
67
+ expect(config.queue.engine?).to eq(true)
68
+
69
+ config.enabled = false
70
+ expect(config.enabled?).to eq(false)
71
+ end
72
+
73
+ specify 'constructor with passed dataset builds compacted config from passed dataset' do
74
+ data_set_based_config = Class.new(Qonfig::DataSet).build do
75
+ setting :test, true
76
+ setting :db do
77
+ setting :creds do
78
+ setting :user, '0exp'
79
+ setting :password, 'test123'
80
+ end
81
+ end
82
+
83
+ validate :test, :boolean
84
+ validate 'db.creds.*', :string
85
+ end
86
+
87
+ compacted_config = Qonfig::Compacted.build_from(data_set_based_config)
88
+
89
+ # NOTE: check readers
90
+ expect(compacted_config.test).to eq(true)
91
+ expect(compacted_config.db.creds.user).to eq('0exp')
92
+ expect(compacted_config.db.creds.password).to eq('test123')
93
+ # and dot-notation:
94
+ expect(compacted_config[:test]).to eq(true)
95
+ expect(compacted_config['db.creds.user']).to eq('0exp')
96
+ expect(compacted_config['db.creds.password']).to eq('test123')
97
+
98
+ # NOTE: check writers
99
+ compacted_config.test = false
100
+ compacted_config.db.creds.user = 'D@iVeR'
101
+ # and dot-notation:
102
+ compacted_config['db.creds.password'] = 'atata123'
103
+
104
+ # NOTE: check new values
105
+ expect(compacted_config.test).to eq(false)
106
+ expect(compacted_config.db.creds.user).to eq('D@iVeR')
107
+ expect(compacted_config.db.creds.password).to eq('atata123')
108
+
109
+ # NOTE: check validators
110
+ expect { compacted_config.test = 123 }.to raise_error(Qonfig::ValidationError)
111
+ expect { compacted_config.db.creds.user = 123 }.to raise_error(Qonfig::ValidationError)
112
+ expect { compacted_config['db.creds.password'] = 123 }.to raise_error(Qonfig::ValidationError)
113
+ end
114
+
115
+ specify 'fails on incorrect datasets passed to constructor' do
116
+ expect { Qonfig::Compacted.build_from(Object.new) }.to raise_error(Qonfig::ArgumentError)
117
+ end
118
+
119
+ specify 'inheritance works as expected' do
120
+ class BaseCompactedConfig < Qonfig::Compacted
121
+ setting :test, true
122
+ setting :db do
123
+ setting :creds do
124
+ setting :user, '0exp'
125
+ setting :password, 'test123'
126
+ end
127
+ end
128
+
129
+ validate :test, :boolean
130
+ validate 'db.creds.*', :string
131
+ end
132
+
133
+ class ChildCompactedConfig < BaseCompactedConfig
134
+ setting :db do
135
+ setting :creds do
136
+ setting :token, 'kekpek'
137
+ end
138
+ end
139
+ end
140
+
141
+ child_compacted_config = ChildCompactedConfig.new
142
+
143
+ # NOTE: check readers
144
+ expect(child_compacted_config.test).to eq(true)
145
+ expect(child_compacted_config.db.creds.user).to eq('0exp')
146
+ expect(child_compacted_config.db.creds.password).to eq('test123')
147
+ expect(child_compacted_config.db.creds.token).to eq('kekpek')
148
+ # and dot-notation:
149
+ expect(child_compacted_config[:test]).to eq(true)
150
+ expect(child_compacted_config['db.creds.user']).to eq('0exp')
151
+ expect(child_compacted_config['db.creds.password']).to eq('test123')
152
+ expect(child_compacted_config['db.creds.token']).to eq('kekpek')
153
+
154
+ # NOTE: check writers
155
+ child_compacted_config.test = false
156
+ child_compacted_config.db.creds.user = 'D@iVeR'
157
+ child_compacted_config.db.creds.password = 'atata123'
158
+ child_compacted_config.db.creds.token = 'trututu'
159
+
160
+ # NOTE: check new values
161
+ expect(child_compacted_config.test).to eq(false)
162
+ expect(child_compacted_config.db.creds.user).to eq('D@iVeR')
163
+ expect(child_compacted_config.db.creds.password).to eq('atata123')
164
+ expect(child_compacted_config.db.creds.token).to eq('trututu')
165
+
166
+ # NOTE: check validators
167
+ # rubocop:disable Layout/LineLength
168
+ expect { child_compacted_config.test = 123 }.to raise_error(Qonfig::ValidationError)
169
+ expect { child_compacted_config.db.creds.user = 123 }.to raise_error(Qonfig::ValidationError)
170
+ expect { child_compacted_config['db.creds.password'] = 123 }.to raise_error(Qonfig::ValidationError)
171
+ expect { child_compacted_config.db.creds.token = 123 }.to raise_error(Qonfig::ValidationError)
172
+ # rubocop:enable Layout/LineLength
173
+ end
174
+
175
+ describe 'instantiation without definition' do
176
+ specify 'creates new Qonfig::Compacted instance' do
177
+ config = Qonfig::Compacted.build do
178
+ setting :api, 'api.overwatch.com'
179
+ setting(:tokens) { setting :internal, 'test123' }
180
+ end
181
+
182
+ expect((class << config; self; end).superclass.superclass).to eq(Qonfig::Compacted)
183
+ expect(config.api).to eq('api.overwatch.com')
184
+ expect(config.tokens.internal).to eq('test123')
185
+ end
186
+
187
+ specify 'can inherit existing Qonfig::Compacted class' do
188
+ base_config_klass = Class.new(Qonfig::Compacted) do
189
+ setting(:creds) { setting :login, 'test123' }
190
+ setting :enabled, true
191
+ end
192
+
193
+ config = Qonfig::Compacted.build(base_config_klass) do
194
+ setting :api, 'api.overwatch.com'
195
+ setting :enabled, false
196
+ setting(:creds) { setting :password, 'kekpek' }
197
+ end
198
+
199
+ expect(config.creds.login).to eq('test123') # NOTE: inherited definition
200
+ expect(config.enabled).to eq(false) # NOTE: redefined setting
201
+ expect(config.creds.password).to eq('kekpek') # NOTE: extended setting "creds"
202
+ expect(config.api).to eq('api.overwatch.com') # NOTE: own setting
203
+ end
204
+ end
205
+
206
+ specify 'Qonfig::DataSet#compacted build compacted config from itself' do
207
+ class CompactCheckConfig < Qonfig::DataSet
208
+ setting :db do
209
+ setting :creds do
210
+ setting :user, 'D@iVeR'
211
+ setting :password, 'test123'
212
+ setting :data, test: false
213
+ end
214
+ end
215
+ setting :logger, nil
216
+ setting :graphql_endpoint, 'https://localhost:1234/graphql'
217
+ end
218
+
219
+ compacted_config = CompactCheckConfig.new.compacted
220
+
221
+ # NOTE: check readers
222
+ expect(compacted_config.db.creds.user).to eq('D@iVeR')
223
+ expect(compacted_config.db.creds.password).to eq('test123')
224
+ expect(compacted_config.db.creds.data).to eq(test: false)
225
+ expect(compacted_config.logger).to eq(nil)
226
+ expect(compacted_config.graphql_endpoint).to eq('https://localhost:1234/graphql')
227
+
228
+ # NOTE: check writers
229
+ # ambigous write is impossible
230
+ expect do
231
+ compacted_config.db = :test
232
+ end.to raise_error(Qonfig::AmbiguousSettingValueError)
233
+ expect do
234
+ compacted_config.db.creds = :test
235
+ end.to raise_error(Qonfig::AmbiguousSettingValueError)
236
+ # regular write is possible :)
237
+ compacted_config.db.creds.user = '0exp'
238
+ compacted_config.db.creds.password = '123test'
239
+ compacted_config.db.creds.data = { no: :errors }
240
+ compacted_config.logger = :logger
241
+ compacted_config.graphql_endpoint = 'https://localhost:4321/graphql'
242
+ # corresponding values was correctly assigned
243
+ expect(compacted_config.db.creds.user).to eq('0exp')
244
+ expect(compacted_config.db.creds.password).to eq('123test')
245
+ expect(compacted_config.db.creds.data).to eq(no: :errors)
246
+ expect(compacted_config.logger).to eq(:logger)
247
+ expect(compacted_config.graphql_endpoint).to eq('https://localhost:4321/graphql')
248
+ end
249
+
250
+ specify 'Qonfig::DataSet.build_compacted - builds compacted config object' do
251
+ compacted_config = Qonfig::DataSet.build_compacted do
252
+ setting(:db) { setting(:creds) { setting :user, '0exp' } }
253
+ setting :logger, :no_logger
254
+ setting :graphql_endpoint, '/graph_dracula'
255
+ end
256
+
257
+ # NOTE: check readers
258
+ expect(compacted_config.db.creds.user).to eq('0exp')
259
+ expect(compacted_config.logger).to eq(:no_logger)
260
+ expect(compacted_config.graphql_endpoint).to eq('/graph_dracula')
261
+
262
+ # NOTE: check writers
263
+ # ambigous write is impossible
264
+ expect do
265
+ compacted_config.db = :test
266
+ end.to raise_error(Qonfig::AmbiguousSettingValueError)
267
+ expect do
268
+ compacted_config.db.creds = :test
269
+ end.to raise_error(Qonfig::AmbiguousSettingValueError)
270
+ # regular write is possible :)
271
+ compacted_config.db.creds.user = 'D@iVeR'
272
+ compacted_config.logger = :logger
273
+ compacted_config.graphql_endpoint = 'https://localhost:4321/graphql'
274
+ # corresponding values was correctly assigned
275
+ expect(compacted_config.db.creds.user).to eq('D@iVeR')
276
+ expect(compacted_config.logger).to eq(:logger)
277
+ expect(compacted_config.graphql_endpoint).to eq('https://localhost:4321/graphql')
278
+ end
279
+ end
280
+
281
+ describe '(.valid_with?) class-level pre-validation checking' do
282
+ specify 'support for do-config notation :)' do
283
+ config_klass = Class.new(Qonfig::Compacted) do
284
+ setting :enabled, false
285
+ setting(:db) { setting :user, 'D@iVeR' }
286
+ validate :enabled, :boolean, strict: true
287
+ validate 'db.#', :text, strict: true
288
+ end
289
+
290
+ # class-level checker
291
+ expect(
292
+ (config_klass.valid_with?(enabled: true) do |conf|
293
+ conf.db.user = '0exp'
294
+ end)
295
+ ).to eq(true)
296
+ expect(
297
+ (config_klass.valid_with?(enabled: false) do |conf|
298
+ conf.db.user = 123
299
+ end)
300
+ ).to eq(false)
301
+ expect(
302
+ (config_klass.valid_with?(enabled: nil) do |conf|
303
+ conf.db.user = 'test'
304
+ end)
305
+ ).to eq(false)
306
+ end
307
+ end
308
+ end