qonfig 0.19.1 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +168 -29
  4. data/lib/qonfig/commands/definition/re_define_option.rb +60 -0
  5. data/lib/qonfig/commands/definition.rb +1 -0
  6. data/lib/qonfig/data_set/class_builder.rb +2 -0
  7. data/lib/qonfig/data_set.rb +5 -5
  8. data/lib/qonfig/dsl.rb +101 -9
  9. data/lib/qonfig/errors.rb +14 -8
  10. data/lib/qonfig/plugins/toml/commands/{expose_toml.rb → definition/expose_toml.rb} +5 -1
  11. data/lib/qonfig/plugins/toml/commands/{load_from_toml.rb → definition/load_from_toml.rb} +5 -1
  12. data/lib/qonfig/plugins/toml/dsl.rb +8 -2
  13. data/lib/qonfig/plugins/toml.rb +2 -2
  14. data/lib/qonfig/settings.rb +4 -2
  15. data/lib/qonfig/{validator/builder → validation/building/instance_builder}/attribute_consistency.rb +14 -14
  16. data/lib/qonfig/{validator/builder.rb → validation/building/instance_builder.rb} +55 -30
  17. data/lib/qonfig/validation/building/predefined_builder.rb +86 -0
  18. data/lib/qonfig/validation/building.rb +8 -0
  19. data/lib/qonfig/{validator/collection.rb → validation/collections/instance_collection.rb} +16 -14
  20. data/lib/qonfig/validation/collections/predefined_registry.rb +145 -0
  21. data/lib/qonfig/validation/collections.rb +8 -0
  22. data/lib/qonfig/validation/predefinition_mixin.rb +15 -0
  23. data/lib/qonfig/{validator → validation/validators}/basic.rb +9 -9
  24. data/lib/qonfig/{validator.rb → validation/validators/composite.rb} +8 -16
  25. data/lib/qonfig/{validator → validation/validators}/method_based.rb +6 -6
  26. data/lib/qonfig/{validator/predefined/common.rb → validation/validators/predefined.rb} +7 -7
  27. data/lib/qonfig/{validator → validation/validators}/proc_based.rb +6 -6
  28. data/lib/qonfig/validation/validators.rb +11 -0
  29. data/lib/qonfig/validation.rb +10 -0
  30. data/lib/qonfig/version.rb +1 -1
  31. data/lib/qonfig.rb +34 -1
  32. data/qonfig.gemspec +1 -1
  33. metadata +23 -26
  34. data/lib/qonfig/validator/dsl.rb +0 -59
  35. data/lib/qonfig/validator/predefined/registry.rb +0 -81
  36. data/lib/qonfig/validator/predefined/registry_control_mixin.rb +0 -44
  37. data/lib/qonfig/validator/predefined.rb +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dab3b453c59fc8f9431ddeb3e0fb3cccd067947bf2275e94d2b75f8862e66c70
4
- data.tar.gz: 7fb3387c500b3d9f738710ed5db17b3d594fffef048b06895498b8710b224257
3
+ metadata.gz: c0c47867d48b4170e321a53b70e527817db87b4dec1b7a4b464d352590501478
4
+ data.tar.gz: ddaa44855f051262fac8477a7ff736d43c896ade3c1c75ee4efa9a89d58ac555
5
5
  SHA512:
6
- metadata.gz: 8317ded309d56239bbf763a4e72f6b0364981f6a2c87831f0dab396f9c9c2de61b8a062ec22f45b58a942731f46f0d171983e0f25cce2d07e2291f98049d8987
7
- data.tar.gz: a06e95e78176a44c7de83548ee5e57f614442ecca6a42b681429cd26f4ef0489cf89ddfec716bf59b96bbd30d7a044a718a020bb9db98fcd5ee8d6f9a9629b86
6
+ metadata.gz: 220ba3ccc61ce56a09ef245b07c36a8a7e695688e57e98039882ecb8917fa83bca7fe5e075fd5b68d671639a04d7fe92ad600587c9a20717296675c6ecb8053b
7
+ data.tar.gz: 05cf1fcac1bdff9c4414530ab1561057b52cfc0903fd64c1af0962b49bd91702e662d2f0467494862ad0bda633842a05e3665d68a91fe61316760c97adbf8a31
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.20.0] - 2019-12-01
5
+ ### Added
6
+ - Extended **Validation API**: you can define your own predefined validators via `.define_validator(name, &validation)` directive;
7
+ - `re_setting` - a special DSL command method that fully redefines existing settings (redefines existing settings instead of reopening them);
8
+
4
9
  ## [0.19.1] - 2019-11-29
5
10
  ### Changed
6
11
  - Support for Ruby 2.3 has ended.
data/README.md CHANGED
@@ -60,6 +60,7 @@ require 'qonfig'
60
60
  - [Proc-based validation](#proc-based-validation)
61
61
  - [Method-based validation](#method-based-validation)
62
62
  - [Predefined validations](#predefined-validations)
63
+ - [Custom predefined validators](#custom-predefined-validators)
63
64
  - [Validation of potential setting values](#validation-of-potential-setting-values)
64
65
  - [Work with files](#work-with-files)
65
66
  - **Setting keys definition**
@@ -98,6 +99,12 @@ require 'qonfig'
98
99
 
99
100
  ### Definition and Access
100
101
 
102
+ - `setting(name, value)` - define setting with corresponding name and value;
103
+ - `setting(name) { setting(name, value); ... }` - define nested settings OR reopen existing nested setting and define some new nested settings;
104
+ - `re_setting(name, value)`, `re_setting(name) { ... }` - re-define existing setting (or define new if the original does not exist);
105
+ - accessing: [access via method](#access-via-method), [access via index-method \[\]](#access-via-index-method-),
106
+ [.dig](#dig), [.slice](#slice), [.slice_value](#slice_value), [.subset](#subset);
107
+
101
108
  ```ruby
102
109
  # --- definition ---
103
110
  class Config < Qonfig::DataSet
@@ -106,14 +113,20 @@ class Config < Qonfig::DataSet
106
113
 
107
114
  # nested setting
108
115
  setting :vendor_api do
109
- setting :host, 'app.service.com'
116
+ setting :host, 'vendor.service.com'
110
117
  end
111
118
 
112
119
  setting :enable_graphql, false
113
120
 
114
121
  # nested setting reopening
115
122
  setting :vendor_api do
116
- setting :user, 'test_user'
123
+ setting :user, 'simple_user'
124
+ end
125
+
126
+ # re-definition of existing setting (drop the old - make the new)
127
+ re_setting :vendor_api do
128
+ setting :domain, 'api.service.com'
129
+ setting :login, 'test_user'
117
130
  end
118
131
 
119
132
  # deep nesting
@@ -133,8 +146,8 @@ config = Config.new # your configuration object instance
133
146
  ```ruby
134
147
  # get option value via method
135
148
  config.settings.project_id # => nil
136
- config.settings.vendor_api.host # => 'app.service.com'
137
- config.settings.vendor_api.user # => 'test_user'
149
+ config.settings.vendor_api.domain # => 'app.service.com'
150
+ config.settings.vendor_api.login # => 'test_user'
138
151
  config.settings.enable_graphql # => false
139
152
  ```
140
153
 
@@ -145,14 +158,14 @@ config.settings.enable_graphql # => false
145
158
  ```ruby
146
159
  # get option value via index (with indifferent (string / symbol / mixed) access)
147
160
  config.settings[:project_id] # => nil
148
- config.settings[:vendor_api][:host] # => 'app.service.com'
149
- config.settings[:vendor_api][:user] # => 'test_user'
161
+ config.settings[:vendor_api][:domain] # => 'app.service.com'
162
+ config.settings[:vendor_api][:login] # => 'test_user'
150
163
  config.settings[:enable_graphql] # => false
151
164
 
152
165
  # get option value via index (with indifferent (string / symbol / mixed) access)
153
166
  config.settings['project_id'] # => nil
154
- config.settings['vendor_api']['host'] # => 'app.service.com'
155
- config.settings['vendor_api']['user'] # => 'test_user'
167
+ config.settings['vendor_api']['domain'] # => 'app.service.com'
168
+ config.settings['vendor_api']['login'] # => 'test_user'
156
169
  config.settings['enable_graphql'] # => false
157
170
 
158
171
  # get option value directly via index (with indifferent access)
@@ -165,11 +178,11 @@ config[:enable_graphql] # => false
165
178
  - with dot-notation:
166
179
 
167
180
  ```ruby
168
- config.settings['vendor_api.host'] # => 'app.service.com'
169
- config.settings['vendor_api.user'] # => 'test_user'
181
+ config.settings['vendor_api.domain'] # => 'app.service.com'
182
+ config.settings['vendor_api.login'] # => 'test_user'
170
183
 
171
- config['vendor_api.host'] # => 'app.service.com'
172
- config['vendor_api.user'] # => 'test_user'
184
+ config['vendor_api.domain'] # => 'app.service.com'
185
+ config['vendor_api.login'] # => 'test_user'
173
186
  ```
174
187
 
175
188
  #### .dig
@@ -178,15 +191,15 @@ config['vendor_api.user'] # => 'test_user'
178
191
 
179
192
  ```ruby
180
193
  # get option value in Hash#dig manner (and fail when the required key does not exist);
181
- config.dig(:vendor_api, :host) # => 'app.service.com' # (key exists)
182
- config.dig(:vendor_api, :port) # => Qonfig::UnknownSettingError # (key does not exist)
194
+ config.dig(:vendor_api, :domain) # => 'app.service.com' # (key exists)
195
+ config.dig(:vendor_api, :login) # => Qonfig::UnknownSettingError # (key does not exist)
183
196
  ```
184
197
 
185
198
  - with dot-notation:
186
199
 
187
200
  ```ruby
188
- config.dig('vendor_api.host') # => 'app.service.com' # (key exists)
189
- config.dig('vendor_api.port') # => Qonfig::UnknownSettingError # (key does not exist)
201
+ config.dig('vendor_api.domain') # => 'app.service.com' # (key exists)
202
+ config.dig('vendor_api.login') # => Qonfig::UnknownSettingError # (key does not exist)
190
203
  ```
191
204
 
192
205
  #### .slice
@@ -195,8 +208,8 @@ config.dig('vendor_api.port') # => Qonfig::UnknownSettingError # (key does not e
195
208
 
196
209
  ```ruby
197
210
  # get a hash slice of setting options (and fail when the required key does not exist);
198
- config.slice(:vendor_api) # => { 'vendor_api' => { 'host' => 'app_service', 'user' => 'test_user' } }
199
- config.slice(:vendor_api, :user) # => { 'user' => 'test_user' }
211
+ config.slice(:vendor_api) # => { 'vendor_api' => { 'domain' => 'app_service', 'login' => 'test_user' } }
212
+ config.slice(:vendor_api, :login) # => { 'login' => 'test_user' }
200
213
  config.slice(:project_api) # => Qonfig::UnknownSettingError # (key does not exist)
201
214
  config.slice(:vendor_api, :port) # => Qonfig::UnknownSettingError # (key does not exist)
202
215
  ```
@@ -204,7 +217,7 @@ config.slice(:vendor_api, :port) # => Qonfig::UnknownSettingError # (key does no
204
217
  - with dot-notation:
205
218
 
206
219
  ```ruby
207
- config.slice('vendor_api.user') # => { 'user' => 'test_user' }
220
+ config.slice('vendor_api.login') # => { 'loign' => 'test_user' }
208
221
  config.slice('vendor_api.port') # => Qonfig::UnknownSettingError # (key does not exist)
209
222
  ```
210
223
 
@@ -217,8 +230,8 @@ config.slice('vendor_api.port') # => Qonfig::UnknownSettingError # (key does not
217
230
  # get value from the slice of setting options using the given key set
218
231
  # (and fail when the required key does not exist) (works in slice manner);
219
232
 
220
- config.slice_value(:vendor_api) # => { 'host' => 'app_service', 'user' => 'test_user' }
221
- config.slice_value(:vendor_api, :user) # => 'test_user'
233
+ config.slice_value(:vendor_api) # => { 'domain' => 'app_service', 'login' => 'test_user' }
234
+ config.slice_value(:vendor_api, :login) # => 'test_user'
222
235
  config.slice_value(:project_api) # => Qonfig::UnknownSettingError # (key does not exist)
223
236
  config.slice_value(:vendor_api, :port) # => Qonfig::UnknownSettingError # (key does not exist)
224
237
  ```
@@ -226,7 +239,7 @@ config.slice_value(:vendor_api, :port) # => Qonfig::UnknownSettingError # (key d
226
239
  - with dot-notation:
227
240
 
228
241
  ```ruby
229
- config.slice_value('vendor_api.user') # => 'test_user'
242
+ config.slice_value('vendor_api.login') # => 'test_user'
230
243
  config.slice_value('vendor_api.port') # => Qonfig::UnknownSettingError # (key does not exist)
231
244
  ```
232
245
 
@@ -239,17 +252,17 @@ config.slice_value('vendor_api.port') # => Qonfig::UnknownSettingError # (key do
239
252
  # - each key (or key set) represents a requirement of a certain setting key;
240
253
 
241
254
  config.subet(:vendor_api, :enable_graphql)
242
- # => { 'vendor_api' => { 'user' => ..., 'host' => ... }, 'enable_graphql' => false }
255
+ # => { 'vendor_api' => { 'login' => ..., 'domain' => ... }, 'enable_graphql' => false }
243
256
 
244
- config.subset(:project_id, [:vendor_api, :host], [:credentials, :user, :login])
245
- # => { 'project_id' => nil, 'host' => 'app.service.com', 'login' => 'D@iVeR' }
257
+ config.subset(:project_id, [:vendor_api, :domain], [:credentials, :user, :login])
258
+ # => { 'project_id' => nil, 'domain' => 'app.service.com', 'login' => 'D@iVeR' }
246
259
  ```
247
260
 
248
261
  - with dot-notation:
249
262
 
250
263
  ```ruby
251
- config.subset('project_id', 'vendor_api.host', 'credentials.user.login')
252
- # => { 'project_id' => nil, 'host' => 'app.service.com', 'login' => 'D@iVeR' }
264
+ config.subset('project_id', 'vendor_api.domain', 'credentials.user.login')
265
+ # => { 'project_id' => nil, 'domain' => 'app.service.com', 'login' => 'D@iVeR' }
253
266
  ```
254
267
 
255
268
  ---
@@ -1024,6 +1037,19 @@ Sometimes the nesting of configs in your project is quite high, and it makes you
1024
1037
  such code by methods or variables. In order to make developer's life easer `Qonfig` provides a special Import API simplifies the config importing
1025
1038
  (gives you `.import_settings` DSL) and gives an ability to instant config setting export from a config object (gives you `#export_settings` config's method).
1026
1039
 
1040
+ You can use RabbitMQ-like pattern matching in setting key names:
1041
+ - if the setting key name at the current nesting level does not matter - use `*`;
1042
+ - if both the setting key name and nesting level does not matter - use `#`
1043
+ - examples:
1044
+ - `db.settings.user` - matches to `db.settings.user` setting;
1045
+ - `db.settings.*` - matches to all setting keys inside `db.settings` group of settings;
1046
+ - `db.*.user` - matches to all `user` setting keys at the first level of `db` group of settings;
1047
+ - `#.user` - matches to all `user` setting keys;
1048
+ - `service.#.password` - matches to all `password` setting keys at all levels of `service` group of settings;
1049
+ - `#` - matches to ALL setting keys;
1050
+ - `*` - matches to all setting keys at the root level;
1051
+ - and etc;
1052
+
1027
1053
  ---
1028
1054
 
1029
1055
  ### Import config settings
@@ -1055,6 +1081,8 @@ AppConfig = Qonfig::DataSet.build do
1055
1081
  end
1056
1082
  end
1057
1083
  end
1084
+
1085
+ setting :graphql_api, false
1058
1086
  end
1059
1087
  ```
1060
1088
 
@@ -1153,6 +1181,47 @@ service = ServiceObject.new
1153
1181
  service.credentials # => { "account" => { "login" => "D@iVeR", "auth_token" => "IAdkoa0@()1239uA"} }
1154
1182
  ```
1155
1183
 
1184
+ #### Immport with pattern-matching
1185
+
1186
+ - import root keys only: `import_settings(config_object, '*')`;
1187
+ - import all keys: `import_settings(config_object, '#')`;
1188
+ - import the subset of keys: `import_settings(config_object, 'group.*.group.#')` (pattern-mathcing usage);
1189
+
1190
+ ```ruby
1191
+ class ServiceObject
1192
+ include Qonfig::Imports
1193
+
1194
+ # import all settings from web_api.credentials subset
1195
+ import_settings(AppConfig, 'web_api.credentials.#')
1196
+ # generated instance methods:
1197
+ # => service.account
1198
+ # => service.login
1199
+ # => service.auth_token
1200
+
1201
+ # import only the root keys from web_api.credentials.account subset
1202
+ import_settings(AppConfig, 'web_api.credentials.account.*')
1203
+ # generated instance methods:
1204
+ # => service.login
1205
+ # => service.auth_token
1206
+
1207
+ # import only the root keys
1208
+ import_settings(AppConfig, '*')
1209
+ # generated instance methods:
1210
+ # => service.web_api
1211
+ # => service.graphql_api
1212
+
1213
+ # import ALL keys
1214
+ import_Settings(AppConfig, '#')
1215
+ # generated instance methods:
1216
+ # => service.web_api
1217
+ # => service.credentials
1218
+ # => service.account
1219
+ # => service.login
1220
+ # => service.auth_token
1221
+ # => service.graphql_api
1222
+ end
1223
+ ```
1224
+
1156
1225
  ---
1157
1226
 
1158
1227
  ### Export config settings
@@ -1179,6 +1248,8 @@ class Config < Qonfig::DataSet
1179
1248
  end
1180
1249
  end
1181
1250
  end
1251
+
1252
+ setting :graphql_api, false
1182
1253
  end
1183
1254
 
1184
1255
  class ServiceObject; end
@@ -1192,6 +1263,12 @@ service.config_account # => NoMethodError
1192
1263
  config.export_settings(service, 'web_api.credentials.account', prefix: 'config_')
1193
1264
 
1194
1265
  service.config_account # => { "login" => "D@iVeR", "auth_token" => "IAdkoa0@()1239uA" }
1266
+
1267
+ # NOTE: export settings with pattern matching
1268
+ config.export_settings(service, '*') # export root settings
1269
+
1270
+ service.web_api # => { 'credentials' => { 'account' => { ... } }, 'graphql_api' => false }
1271
+ service.graphql_api # => false
1195
1272
  ```
1196
1273
 
1197
1274
  ---
@@ -1203,6 +1280,7 @@ service.config_account # => { "login" => "D@iVeR", "auth_token" => "IAdkoa0@()12
1203
1280
  - [Proc-based validation](#proc-based-validation)
1204
1281
  - [Method-based validation](#method-based-validation)
1205
1282
  - [Predefined validations](#predefined-validations)
1283
+ - [Custom predefined validators](#custom-predefined-validators)
1206
1284
  - [Validation of potential setting values](#validation-of-potential-setting-values)
1207
1285
 
1208
1286
  ---
@@ -1224,7 +1302,7 @@ If you want to check the config object completely you can define a custom valida
1224
1302
  - `strict: false` ignores validations for settings with `nil` (allows `nil` value);
1225
1303
  - `strict: true` does not ignores validations for settings with `nil`;
1226
1304
  - `strict: false` is used by default;
1227
- - provides special [key search pattern](#key-search-pattern) for matching setting key names;
1305
+ - provides a special [key search pattern](#key-search-pattern) for matching setting key names;
1228
1306
  - you can validate potential setting values without any assignment ([documentation](#validation-of-potential-setting-values))
1229
1307
  - uses the [key search pattern](#key-search-pattern) for definging what the setting key should be validated;
1230
1308
  - you can define your own custom validation logic and validate dataset instance completely;
@@ -1261,6 +1339,7 @@ If you want to check the config object completely you can define a custom valida
1261
1339
  - provides a **set of standard validations** ([documentation](#predefined-validations)):
1262
1340
  - DSL: `validate 'key.pattern', :predefned_validator`;
1263
1341
  - supports `strict` behavior;
1342
+ - you can define your own predefined validators (class-related and global-related) ([documentation](#custom-predefined-validators));
1264
1343
 
1265
1344
  ---
1266
1345
 
@@ -1477,6 +1556,67 @@ config.settings.ignorance = nil # => Qonfig::ValidationError (cant be nil)
1477
1556
 
1478
1557
  ---
1479
1558
 
1559
+ ### Custom predefined validators
1560
+
1561
+ - DSL: `.define_validator(name, &validation) { |value| ... }` - create your own predefined validator;
1562
+ - **class-level**: define validators related only to the concrete config class;
1563
+ - **global-level**: define validators related to all config classes (`Qonfig::DataSet.define_validator`);
1564
+ - you can re-define any global and inherited validator (at class level);
1565
+ - you can re-define any already registered global validator on `Qonfig::DataSet` (at global-level);
1566
+
1567
+ #### Define your own class-level validator
1568
+
1569
+ ```ruby
1570
+ class Config < Qonfig::DataSet
1571
+ # NOTE: definition
1572
+ define_validator(:user_type) { |value| value.is_a?(User) }
1573
+
1574
+ setting :admin # some key
1575
+
1576
+ validate :admin, :user_type # NOTE: useage
1577
+ end
1578
+ ```
1579
+
1580
+ #### Defin new global validator
1581
+
1582
+ ```ruby
1583
+ Qonfig::DataSet.define_validator(:secured_value) do |value|
1584
+ value == '***'
1585
+ end
1586
+
1587
+ class Config < Qonfig::DataSet
1588
+ setting :password
1589
+ validate :password, :secured_value
1590
+ end
1591
+ ```
1592
+
1593
+ #### Re-definition of existing validators in child classes
1594
+
1595
+ ```ruby
1596
+ class Config < Qonfig::DataSet
1597
+ # NOTE: redefine existing :text validator only in Config class
1598
+ define_validator(:text) { |value| value.is_a?(String) }
1599
+
1600
+ # NOTE: some custom validator that can be redefined in child classes
1601
+ define_validator(:user) { |value| value.is_a?(User) }
1602
+ end
1603
+
1604
+ class SubConfig < Qonfig
1605
+ define_validator(:user) { |value| value.is_a?(AdminUser) } # NOTE: redefine inherited :user validator
1606
+ end
1607
+ ```
1608
+
1609
+ #### Re-definition of existing global validators
1610
+
1611
+ ```ruby
1612
+ # NOTE: redefine already existing :numeric validator
1613
+ Qonfig::DataSet.define_validator(:numeric) do |value|
1614
+ value.is_a?(Numeric) || (value.is_a?(String) && value.match?(/\A\d+\.*\d+\z/))
1615
+ end
1616
+ ```
1617
+
1618
+ ---
1619
+
1480
1620
  ### Validation of potential setting values
1481
1621
 
1482
1622
  - (**instance-level**) `#valid_with?(configurations = {})` - check that current config instalce will be valid with passed configurations;
@@ -2776,7 +2916,6 @@ config = Config.new
2776
2916
  - support for persistent data storages (we want to store configs in multiple databases and files);
2777
2917
  - Rails reload plugin;
2778
2918
  - **Minor**:
2779
- - custom global (and class-level) validators (with a special Validator Definition DSL);
2780
2919
 
2781
2920
  ## Contributing
2782
2921
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.20.0
5
+ class Qonfig::Commands::Definition::ReDefineOption < Qonfig::Commands::Base
6
+ # @since 0.20.0
7
+ self.inheritable = true
8
+
9
+ # @return [Symbol, String]
10
+ #
11
+ # @api private
12
+ # @since 0.20.0
13
+ attr_reader :key
14
+
15
+ # @return [Object]
16
+ #
17
+ # @api private
18
+ # @since 0.20.0
19
+ attr_reader :value
20
+
21
+ # @return [Proc, NilClass]
22
+ #
23
+ # @api private
24
+ # @since 0.20.0
25
+ attr_reader :nested_data_set_klass
26
+
27
+ # @param key [Symbol, String]
28
+ # @param value [Object]
29
+ #
30
+ # @raise [Qonfig::ArgumentError]
31
+ # @raise [Qonfig::CoreMethodIntersectionError]
32
+ #
33
+ # @api private
34
+ # @since 0.20.0
35
+ def initialize(key, value, nested_definitions)
36
+ Qonfig::Settings::KeyGuard.prevent_incomparabilities!(key)
37
+
38
+ @key = key
39
+ @value = value
40
+ @nested_data_set_klass = Class.new(Qonfig::DataSet).tap do |data_set|
41
+ data_set.instance_eval(&nested_definitions)
42
+ end if nested_definitions
43
+ end
44
+
45
+ # @param data_set [Qonfig::DataSet]
46
+ # @param settings [Qonfig::Settings]
47
+ # @return [void]
48
+ #
49
+ # @api private
50
+ # @since 0.20.0
51
+ def call(data_set, settings)
52
+ if nested_data_set_klass
53
+ nested_settings = nested_data_set_klass.new.settings
54
+ nested_settings.__mutation_callbacks__.add(settings.__mutation_callbacks__)
55
+ settings.__define_setting__(key, nested_settings, with_redefinition: true)
56
+ else
57
+ settings.__define_setting__(key, value, with_redefinition: true)
58
+ end
59
+ end
60
+ end
@@ -5,6 +5,7 @@
5
5
  module Qonfig::Commands::Definition
6
6
  require_relative 'definition/add_option'
7
7
  require_relative 'definition/add_nested_option'
8
+ require_relative 'definition/re_define_option'
8
9
  require_relative 'definition/compose'
9
10
  require_relative 'definition/load_from_yaml'
10
11
  require_relative 'definition/load_from_json'
@@ -33,6 +33,8 @@ module Qonfig::DataSet::ClassBuilder
33
33
  def inherit(base_klass:, child_klass:)
34
34
  child_klass.definition_commands.concat(base_klass.definition_commands)
35
35
  child_klass.instance_commands.concat(base_klass.instance_commands, &:inheritable?)
36
+ child_klass.predefined_validators.merge(base_klass.predefined_validators)
37
+ child_klass.validators.concat(base_klass.validators)
36
38
  end
37
39
  end
38
40
  end
@@ -7,11 +7,9 @@ class Qonfig::DataSet # rubocop:disable Metrics/ClassLength
7
7
  require_relative 'data_set/lock'
8
8
 
9
9
  # @since 0.1.0
10
+ # @version 0.20.0
10
11
  extend Qonfig::DSL
11
12
 
12
- # @since 0.13.0
13
- extend Qonfig::Validator::DSL
14
-
15
13
  class << self
16
14
  # @param base_dataset_klass [Class<Qonfig::DataSet>]
17
15
  # @param config_klass_definitions [Proc]
@@ -427,10 +425,11 @@ class Qonfig::DataSet # rubocop:disable Metrics/ClassLength
427
425
 
428
426
  private
429
427
 
430
- # @return [Qonfig::Validator]
428
+ # @return [Qonfig::Validation::Validators::Composite]
431
429
  #
432
430
  # @api private
433
431
  # @since 0.13.0
432
+ # @version 0.20.0
434
433
  attr_reader :validator
435
434
 
436
435
  # @return [void]
@@ -448,8 +447,9 @@ class Qonfig::DataSet # rubocop:disable Metrics/ClassLength
448
447
  #
449
448
  # @api private
450
449
  # @since 0.13.0
450
+ # @version 0.20.0
451
451
  def build_validator
452
- @validator = Qonfig::Validator.new(self)
452
+ @validator = Qonfig::Validation::Validators::Composite.new(self)
453
453
  end
454
454
 
455
455
  # @param settings_map [Hash]