anyway_config 2.0.6 → 2.2.2
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/CHANGELOG.md +241 -181
 - data/README.md +237 -12
 - data/lib/.rbnext/1995.next/anyway/config.rb +438 -0
 - data/lib/.rbnext/1995.next/anyway/dynamic_config.rb +31 -0
 - data/lib/.rbnext/1995.next/anyway/env.rb +56 -0
 - data/lib/.rbnext/1995.next/anyway/loaders/base.rb +21 -0
 - data/lib/.rbnext/1995.next/anyway/tracing.rb +181 -0
 - data/lib/.rbnext/2.7/anyway/auto_cast.rb +39 -19
 - data/lib/.rbnext/2.7/anyway/config.rb +60 -15
 - data/lib/.rbnext/2.7/anyway/rails/loaders/yaml.rb +30 -0
 - data/lib/.rbnext/2.7/anyway/rbs.rb +92 -0
 - data/lib/.rbnext/2.7/anyway/settings.rb +79 -0
 - data/lib/.rbnext/2.7/anyway/tracing.rb +1 -1
 - data/lib/.rbnext/2.7/anyway/type_casting.rb +143 -0
 - data/lib/.rbnext/3.0/anyway/auto_cast.rb +53 -0
 - data/lib/.rbnext/{2.8 → 3.0}/anyway/config.rb +60 -15
 - data/lib/.rbnext/{2.8 → 3.0}/anyway/loaders/base.rb +0 -0
 - data/lib/.rbnext/{2.8 → 3.0}/anyway/loaders.rb +0 -0
 - data/lib/.rbnext/{2.8 → 3.0}/anyway/tracing.rb +1 -1
 - data/lib/anyway/auto_cast.rb +39 -19
 - data/lib/anyway/config.rb +74 -29
 - data/lib/anyway/dynamic_config.rb +6 -2
 - data/lib/anyway/env.rb +1 -1
 - data/lib/anyway/ext/deep_dup.rb +12 -0
 - data/lib/anyway/ext/hash.rb +0 -12
 - data/lib/anyway/loaders/base.rb +1 -1
 - data/lib/anyway/loaders/env.rb +3 -1
 - data/lib/anyway/loaders/yaml.rb +9 -5
 - data/lib/anyway/option_parser_builder.rb +1 -3
 - data/lib/anyway/optparse_config.rb +5 -7
 - data/lib/anyway/rails/loaders/credentials.rb +4 -4
 - data/lib/anyway/rails/loaders/secrets.rb +6 -8
 - data/lib/anyway/rails/loaders/yaml.rb +11 -0
 - data/lib/anyway/rails/settings.rb +9 -2
 - data/lib/anyway/rbs.rb +92 -0
 - data/lib/anyway/settings.rb +52 -2
 - data/lib/anyway/tracing.rb +6 -6
 - data/lib/anyway/type_casting.rb +134 -0
 - data/lib/anyway/utils/deep_merge.rb +21 -0
 - data/lib/anyway/version.rb +1 -1
 - data/lib/anyway_config.rb +4 -0
 - data/sig/anyway_config.rbs +129 -0
 - metadata +42 -15
 - data/lib/.rbnext/2.7/anyway/option_parser_builder.rb +0 -31
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -42,12 +42,14 @@ For version 1.x see the [1-4-stable branch](https://github.com/palkan/anyway_con 
     | 
|
| 
       42 
42 
     | 
    
         
             
              - [Generators](#generators)
         
     | 
| 
       43 
43 
     | 
    
         
             
            - [Using with Ruby applications](#using-with-ruby)
         
     | 
| 
       44 
44 
     | 
    
         
             
            - [Environment variables](#environment-variables)
         
     | 
| 
      
 45 
     | 
    
         
            +
            - [Type coercion](#type-coercion)
         
     | 
| 
       45 
46 
     | 
    
         
             
            - [Local configuration](#local-files)
         
     | 
| 
       46 
47 
     | 
    
         
             
            - [Data loaders](#data-loaders)
         
     | 
| 
       47 
48 
     | 
    
         
             
            - [Source tracing](#tracing)
         
     | 
| 
       48 
49 
     | 
    
         
             
            - [Pattern matching](#pattern-matching)
         
     | 
| 
       49 
50 
     | 
    
         
             
            - [Test helpers](#test-helpers)
         
     | 
| 
       50 
51 
     | 
    
         
             
            - [OptionParser integration](#optionparser-integration)
         
     | 
| 
      
 52 
     | 
    
         
            +
            - [RBS support](#rbs-support)
         
     | 
| 
       51 
53 
     | 
    
         | 
| 
       52 
54 
     | 
    
         
             
            ## Main concepts
         
     | 
| 
       53 
55 
     | 
    
         | 
| 
         @@ -94,7 +96,7 @@ Or adding to your project: 
     | 
|
| 
       94 
96 
     | 
    
         | 
| 
       95 
97 
     | 
    
         
             
            ```ruby
         
     | 
| 
       96 
98 
     | 
    
         
             
            # Gemfile
         
     | 
| 
       97 
     | 
    
         
            -
            gem "anyway_config", "~> 2.0 
     | 
| 
      
 99 
     | 
    
         
            +
            gem "anyway_config", "~> 2.0"
         
     | 
| 
       98 
100 
     | 
    
         
             
            ```
         
     | 
| 
       99 
101 
     | 
    
         | 
| 
       100 
102 
     | 
    
         
             
            ### Supported Ruby versions
         
     | 
| 
         @@ -269,6 +271,7 @@ This feature is similar to `Rails.application.config_for` but more powerful: 
     | 
|
| 
       269 
271 
     | 
    
         
             
            | Load data from environment | ❌ | ✅ |
         
     | 
| 
       270 
272 
     | 
    
         
             
            | Load data from [custom sources](#data-loaders) | ❌ | ✅ |
         
     | 
| 
       271 
273 
     | 
    
         
             
            | Local config files | ❌ | ✅ |
         
     | 
| 
      
 274 
     | 
    
         
            +
            | Type coercion | ❌ | ✅ |
         
     | 
| 
       272 
275 
     | 
    
         
             
            | [Source tracing](#tracing) | ❌ | ✅ |
         
     | 
| 
       273 
276 
     | 
    
         
             
            | Return Hash with indifferent access | ❌ | ✅ |
         
     | 
| 
       274 
277 
     | 
    
         
             
            | Support ERB\* within `config/app.yml` | ✅ | ✅ |
         
     | 
| 
         @@ -329,7 +332,9 @@ and then use [Rails generators](#generators) to make your application Anyway Con 
     | 
|
| 
       329 
332 
     | 
    
         | 
| 
       330 
333 
     | 
    
         
             
            Your config is filled up with values from the following sources (ordered by priority from low to high):
         
     | 
| 
       331 
334 
     | 
    
         | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
      
 335 
     | 
    
         
            +
            1) **YAML configuration files**: `RAILS_ROOT/config/my_cool_gem.yml`.
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
            Rails environment is used as the namespace (required); supports `ERB`:
         
     | 
| 
       333 
338 
     | 
    
         | 
| 
       334 
339 
     | 
    
         
             
            ```yml
         
     | 
| 
       335 
340 
     | 
    
         
             
            test:
         
     | 
| 
         @@ -341,9 +346,51 @@ development: 
     | 
|
| 
       341 
346 
     | 
    
         
             
              port: 3000
         
     | 
| 
       342 
347 
     | 
    
         
             
            ```
         
     | 
| 
       343 
348 
     | 
    
         | 
| 
       344 
     | 
    
         
            -
             
     | 
| 
      
 349 
     | 
    
         
            +
            ### Multi-env configuration
         
     | 
| 
      
 350 
     | 
    
         
            +
             
     | 
| 
      
 351 
     | 
    
         
            +
            _⚡️ This feature will be turned on by default in the future releases. You can turn it on now via `config.anyway_config.future.use :unwrap_known_environments`._
         
     | 
| 
       345 
352 
     | 
    
         | 
| 
       346 
     | 
    
         
            -
             
     | 
| 
      
 353 
     | 
    
         
            +
            If the YML does not have keys that are one of the "known" Rails environments (development, production, test)—the same configuration will be available in all environments, similar to non-Rails behavior:
         
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
            ```yml
         
     | 
| 
      
 356 
     | 
    
         
            +
            host: localhost
         
     | 
| 
      
 357 
     | 
    
         
            +
            port: 3002
         
     | 
| 
      
 358 
     | 
    
         
            +
            # These values will be active in all environments
         
     | 
| 
      
 359 
     | 
    
         
            +
            ```
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
            To extend the list of known environments, use the setting in the relevant part of your Rails code:
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 364 
     | 
    
         
            +
            Rails.application.config.anyway_config.known_environments << "staging"
         
     | 
| 
      
 365 
     | 
    
         
            +
            ```
         
     | 
| 
      
 366 
     | 
    
         
            +
             
     | 
| 
      
 367 
     | 
    
         
            +
            If your YML defines at least a single "environmental" top-level, you _have_ to separate all your settings per-environment. You can't mix and match:
         
     | 
| 
      
 368 
     | 
    
         
            +
             
     | 
| 
      
 369 
     | 
    
         
            +
            ```yml
         
     | 
| 
      
 370 
     | 
    
         
            +
            staging:
         
     | 
| 
      
 371 
     | 
    
         
            +
              host: localhost # This value will be loaded when Rails.env.staging? is true
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
            port: 3002 # This value will not be loaded at all
         
     | 
| 
      
 374 
     | 
    
         
            +
            ```
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
            You can specify the lookup path for YAML files in one of the following ways:
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
            - By setting `config.anyway_config.default_config_path` to a target directory path:
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 381 
     | 
    
         
            +
            config.anyway_config.default_config_path = "/etc/configs"
         
     | 
| 
      
 382 
     | 
    
         
            +
            config.anyway_config.default_config_path = Rails.root.join("etc", "configs")
         
     | 
| 
      
 383 
     | 
    
         
            +
            ```
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
            - By setting `config.anyway_config.default_config_path` to a Proc, which accepts a config name and returns the path:
         
     | 
| 
      
 386 
     | 
    
         
            +
             
     | 
| 
      
 387 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 388 
     | 
    
         
            +
            config.anyway_config.default_config_path = ->(name) { Rails.root.join("data", "configs", "#{name}.yml") }
         
     | 
| 
      
 389 
     | 
    
         
            +
            ```
         
     | 
| 
      
 390 
     | 
    
         
            +
             
     | 
| 
      
 391 
     | 
    
         
            +
            - By overriding a specific config YML file path via the `<NAME>_CONF` env variable, e.g., `MYCOOLGEM_CONF=path/to/cool.yml`
         
     | 
| 
      
 392 
     | 
    
         
            +
             
     | 
| 
      
 393 
     | 
    
         
            +
            2) **Rails secrets**: `Rails.application.secrets.my_cool_gem` (if `secrets.yml` present).
         
     | 
| 
       347 
394 
     | 
    
         | 
| 
       348 
395 
     | 
    
         
             
            ```yml
         
     | 
| 
       349 
396 
     | 
    
         
             
            # config/secrets.yml
         
     | 
| 
         @@ -352,7 +399,7 @@ development: 
     | 
|
| 
       352 
399 
     | 
    
         
             
                port: 4444
         
     | 
| 
       353 
400 
     | 
    
         
             
            ```
         
     | 
| 
       354 
401 
     | 
    
         | 
| 
       355 
     | 
    
         
            -
             
     | 
| 
      
 402 
     | 
    
         
            +
            3) **Rails credentials**: `Rails.application.credentials.my_cool_gem` (if supported):
         
     | 
| 
       356 
403 
     | 
    
         | 
| 
       357 
404 
     | 
    
         
             
            ```yml
         
     | 
| 
       358 
405 
     | 
    
         
             
            my_cool_gem:
         
     | 
| 
         @@ -361,7 +408,7 @@ my_cool_gem: 
     | 
|
| 
       361 
408 
     | 
    
         | 
| 
       362 
409 
     | 
    
         
             
            **NOTE:** You can backport Rails 6 per-environment credentials to Rails 5.2 app using [this patch](https://gist.github.com/palkan/e27e4885535ff25753aefce45378e0cb).
         
     | 
| 
       363 
410 
     | 
    
         | 
| 
       364 
     | 
    
         
            -
             
     | 
| 
      
 411 
     | 
    
         
            +
            4) **Environment variables**: `ENV['MYCOOLGEM_*']`.
         
     | 
| 
       365 
412 
     | 
    
         | 
| 
       366 
413 
     | 
    
         
             
            See [environment variables](#environment-variables).
         
     | 
| 
       367 
414 
     | 
    
         | 
| 
         @@ -407,6 +454,22 @@ config.anyway_config.autoload_static_config_path = "path/to/configs" 
     | 
|
| 
       407 
454 
     | 
    
         
             
            **NOTE:** Configs loaded from the `autoload_static_config_path` are **not reloaded in development**. We call them _static_. So, it makes sense to keep only configs necessary for initialization in this folder. Other configs, _dynamic_, could be stored in `app/configs`.
         
     | 
| 
       408 
455 
     | 
    
         
             
            Or you can store everything in `app/configs` by setting `config.anyway_config.autoload_static_config_path = "app/configs"`.
         
     | 
| 
       409 
456 
     | 
    
         | 
| 
      
 457 
     | 
    
         
            +
            **NOTE 2**: Since _static_ configs are loaded before initializers, it's not possible to use custom inflection Rules (usually defined in `config/initializers/inflections.rb`) to resolve constant names from files. If you rely on custom inflection rules (see, for example, [#81](https://github.com/palkan/anyway_config/issues/81)), we recommend configuration Rails inflector before initialization as well:
         
     | 
| 
      
 458 
     | 
    
         
            +
             
     | 
| 
      
 459 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 460 
     | 
    
         
            +
            # config/application.rb
         
     | 
| 
      
 461 
     | 
    
         
            +
             
     | 
| 
      
 462 
     | 
    
         
            +
            # ...
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
            require_relative "initializers/inflections"
         
     | 
| 
      
 465 
     | 
    
         
            +
             
     | 
| 
      
 466 
     | 
    
         
            +
            module SomeApp
         
     | 
| 
      
 467 
     | 
    
         
            +
              class Application < Rails::Application
         
     | 
| 
      
 468 
     | 
    
         
            +
                # ...
         
     | 
| 
      
 469 
     | 
    
         
            +
              end
         
     | 
| 
      
 470 
     | 
    
         
            +
            end
         
     | 
| 
      
 471 
     | 
    
         
            +
            ```
         
     | 
| 
      
 472 
     | 
    
         
            +
             
     | 
| 
       410 
473 
     | 
    
         
             
            ### Generators
         
     | 
| 
       411 
474 
     | 
    
         | 
| 
       412 
475 
     | 
    
         
             
            Anyway Config provides Rails generators to create new config classes:
         
     | 
| 
         @@ -444,7 +507,7 @@ Alternatively, you can call `rails g anyway:app_config name param1 param2 ...`. 
     | 
|
| 
       444 
507 
     | 
    
         | 
| 
       445 
508 
     | 
    
         
             
            The default data loading mechanism for non-Rails applications is the following (ordered by priority from low to high):
         
     | 
| 
       446 
509 
     | 
    
         | 
| 
       447 
     | 
    
         
            -
             
     | 
| 
      
 510 
     | 
    
         
            +
            1) **YAML configuration files**: `./config/<config-name>.yml`.
         
     | 
| 
       448 
511 
     | 
    
         | 
| 
       449 
512 
     | 
    
         
             
            In pure Ruby apps, we do not know about _environments_ (`test`, `development`, `production`, etc.); thus, we assume that the YAML contains values for a single environment:
         
     | 
| 
       450 
513 
     | 
    
         | 
| 
         @@ -453,9 +516,25 @@ host: localhost 
     | 
|
| 
       453 
516 
     | 
    
         
             
            port: 3000
         
     | 
| 
       454 
517 
     | 
    
         
             
            ```
         
     | 
| 
       455 
518 
     | 
    
         | 
| 
       456 
     | 
    
         
            -
             
     | 
| 
      
 519 
     | 
    
         
            +
            `ERB` is supported if `erb` is loaded (thus, you need to call `require "erb"` somewhere before loading configuration).
         
     | 
| 
      
 520 
     | 
    
         
            +
             
     | 
| 
      
 521 
     | 
    
         
            +
            You can specify the lookup path for YAML files in one of the following ways:
         
     | 
| 
      
 522 
     | 
    
         
            +
             
     | 
| 
      
 523 
     | 
    
         
            +
            - By setting `Anyway::Settings.default_config_path` to a target directory path:
         
     | 
| 
      
 524 
     | 
    
         
            +
             
     | 
| 
      
 525 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 526 
     | 
    
         
            +
            Anyway::Settings.default_config_path = "/etc/configs"
         
     | 
| 
      
 527 
     | 
    
         
            +
            ```
         
     | 
| 
      
 528 
     | 
    
         
            +
             
     | 
| 
      
 529 
     | 
    
         
            +
            - By setting `Anyway::Settings.default_config_path` to a Proc, which accepts a config name and returns the path:
         
     | 
| 
      
 530 
     | 
    
         
            +
             
     | 
| 
      
 531 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 532 
     | 
    
         
            +
            Anyway::Settings.default_config_path = ->(name) { Rails.root.join("data", "configs", "#{name}.yml") }
         
     | 
| 
      
 533 
     | 
    
         
            +
            ```
         
     | 
| 
       457 
534 
     | 
    
         | 
| 
       458 
     | 
    
         
            -
            - ` 
     | 
| 
      
 535 
     | 
    
         
            +
            - By overriding a specific config YML file path via the `<NAME>_CONF` env variable, e.g., `MYCOOLGEM_CONF=path/to/cool.yml`
         
     | 
| 
      
 536 
     | 
    
         
            +
             
     | 
| 
      
 537 
     | 
    
         
            +
            2) **Environment variables**: `ENV['MYCOOLGEM_*']`.
         
     | 
| 
       459 
538 
     | 
    
         | 
| 
       460 
539 
     | 
    
         
             
            See [environment variables](#environment-variables).
         
     | 
| 
       461 
540 
     | 
    
         | 
| 
         @@ -465,13 +544,15 @@ Environmental variables for your config should start with your config name, uppe 
     | 
|
| 
       465 
544 
     | 
    
         | 
| 
       466 
545 
     | 
    
         
             
            For example, if your config name is "mycoolgem", then the env var "MYCOOLGEM_PASSWORD" is used as `config.password`.
         
     | 
| 
       467 
546 
     | 
    
         | 
| 
       468 
     | 
    
         
            -
             
     | 
| 
      
 547 
     | 
    
         
            +
            By default, environment variables are automatically type cast\*:
         
     | 
| 
       469 
548 
     | 
    
         | 
| 
       470 
549 
     | 
    
         
             
            - `"True"`, `"t"` and `"yes"` to `true`;
         
     | 
| 
       471 
550 
     | 
    
         
             
            - `"False"`, `"f"` and `"no"` to `false`;
         
     | 
| 
       472 
551 
     | 
    
         
             
            - `"nil"` and `"null"` to `nil` (do you really need it?);
         
     | 
| 
       473 
552 
     | 
    
         
             
            - `"123"` to 123 and `"3.14"` to 3.14.
         
     | 
| 
       474 
553 
     | 
    
         | 
| 
      
 554 
     | 
    
         
            +
            \* See below for coercion customization.
         
     | 
| 
      
 555 
     | 
    
         
            +
             
     | 
| 
       475 
556 
     | 
    
         
             
            *Anyway Config* supports nested (_hashed_) env variables—just separate keys with double-underscore.
         
     | 
| 
       476 
557 
     | 
    
         | 
| 
       477 
558 
     | 
    
         
             
            For example, "MYCOOLGEM_OPTIONS__VERBOSE" is parsed as `config.options["verbose"]`.
         
     | 
| 
         @@ -489,6 +570,94 @@ If you want to provide a text-like env variable which contains commas then wrap 
     | 
|
| 
       489 
570 
     | 
    
         
             
            MYCOOLGEM = "Nif-Nif, Naf-Naf and Nouf-Nouf"
         
     | 
| 
       490 
571 
     | 
    
         
             
            ```
         
     | 
| 
       491 
572 
     | 
    
         | 
| 
      
 573 
     | 
    
         
            +
            ## Type coercion
         
     | 
| 
      
 574 
     | 
    
         
            +
             
     | 
| 
      
 575 
     | 
    
         
            +
            > 🆕 v2.2.0
         
     | 
| 
      
 576 
     | 
    
         
            +
             
     | 
| 
      
 577 
     | 
    
         
            +
            You can define custom type coercion rules to convert string data to config values. To do that, use `.coerce_types` method:
         
     | 
| 
      
 578 
     | 
    
         
            +
             
     | 
| 
      
 579 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 580 
     | 
    
         
            +
            class CoolConfig < Anyway::Config
         
     | 
| 
      
 581 
     | 
    
         
            +
              config_name :cool
         
     | 
| 
      
 582 
     | 
    
         
            +
              attr_config port: 8080,
         
     | 
| 
      
 583 
     | 
    
         
            +
                host: "localhost",
         
     | 
| 
      
 584 
     | 
    
         
            +
                user: {name: "admin", password: "admin"}
         
     | 
| 
      
 585 
     | 
    
         
            +
             
     | 
| 
      
 586 
     | 
    
         
            +
              coerce_types port: :string, user: {dob: :date}
         
     | 
| 
      
 587 
     | 
    
         
            +
            end
         
     | 
| 
      
 588 
     | 
    
         
            +
             
     | 
| 
      
 589 
     | 
    
         
            +
            ENV["COOL_USER__DOB"] = "1989-07-01"
         
     | 
| 
      
 590 
     | 
    
         
            +
             
     | 
| 
      
 591 
     | 
    
         
            +
            config = CoolConfig.new
         
     | 
| 
      
 592 
     | 
    
         
            +
            config.port == "8080" # Even though we defined the default value as int, it's converted into a string
         
     | 
| 
      
 593 
     | 
    
         
            +
            config.user["dob"] == Date.new(1989, 7, 1) #=> true
         
     | 
| 
      
 594 
     | 
    
         
            +
            ```
         
     | 
| 
      
 595 
     | 
    
         
            +
             
     | 
| 
      
 596 
     | 
    
         
            +
            Type coercion is especially useful to deal with array values:
         
     | 
| 
      
 597 
     | 
    
         
            +
             
     | 
| 
      
 598 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 599 
     | 
    
         
            +
            # To define an array type, provide a hash with two keys:
         
     | 
| 
      
 600 
     | 
    
         
            +
            #  - type — elements type
         
     | 
| 
      
 601 
     | 
    
         
            +
            #  - array: true — mark the parameter as array
         
     | 
| 
      
 602 
     | 
    
         
            +
            coerce_types list: {type: :string, array: true}
         
     | 
| 
      
 603 
     | 
    
         
            +
            ```
         
     | 
| 
      
 604 
     | 
    
         
            +
             
     | 
| 
      
 605 
     | 
    
         
            +
            You can use `type: nil` in case you don't want to coerce values, just convert a value into an array:
         
     | 
| 
      
 606 
     | 
    
         
            +
             
     | 
| 
      
 607 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 608 
     | 
    
         
            +
            # From AnyCable config (sentinels could be represented via strings or hashes)
         
     | 
| 
      
 609 
     | 
    
         
            +
            coerce_types redis_sentinels: {type: nil, array: true}
         
     | 
| 
      
 610 
     | 
    
         
            +
            ```
         
     | 
| 
      
 611 
     | 
    
         
            +
             
     | 
| 
      
 612 
     | 
    
         
            +
            It's also could be useful to explicitly define non-array types (to avoid confusion):
         
     | 
| 
      
 613 
     | 
    
         
            +
             
     | 
| 
      
 614 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 615 
     | 
    
         
            +
            coerce_types non_list: :string
         
     | 
| 
      
 616 
     | 
    
         
            +
            ```
         
     | 
| 
      
 617 
     | 
    
         
            +
             
     | 
| 
      
 618 
     | 
    
         
            +
            Finally, it's possible to disable auto-casting for a particular config completely:
         
     | 
| 
      
 619 
     | 
    
         
            +
             
     | 
| 
      
 620 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 621 
     | 
    
         
            +
            class CoolConfig < Anyway::Config
         
     | 
| 
      
 622 
     | 
    
         
            +
              attr_config port: 8080,
         
     | 
| 
      
 623 
     | 
    
         
            +
                host: "localhost",
         
     | 
| 
      
 624 
     | 
    
         
            +
                user: {name: "admin", password: "admin"}
         
     | 
| 
      
 625 
     | 
    
         
            +
             
     | 
| 
      
 626 
     | 
    
         
            +
              disable_auto_cast!
         
     | 
| 
      
 627 
     | 
    
         
            +
            end
         
     | 
| 
      
 628 
     | 
    
         
            +
             
     | 
| 
      
 629 
     | 
    
         
            +
            ENV["COOL_PORT"] = "443"
         
     | 
| 
      
 630 
     | 
    
         
            +
             
     | 
| 
      
 631 
     | 
    
         
            +
            CoolConfig.new.port == "443" #=> true
         
     | 
| 
      
 632 
     | 
    
         
            +
            ```
         
     | 
| 
      
 633 
     | 
    
         
            +
             
     | 
| 
      
 634 
     | 
    
         
            +
            **IMPORTANT**: Values provided explicitly (via attribute writers) are not coerced. Coercion is only happening during the load phase.
         
     | 
| 
      
 635 
     | 
    
         
            +
             
     | 
| 
      
 636 
     | 
    
         
            +
            The following types are supported out-of-the-box: `:string`, `:integer`, `:float`, `:date`, `:datetime`, `:uri`, `:boolean`.
         
     | 
| 
      
 637 
     | 
    
         
            +
             
     | 
| 
      
 638 
     | 
    
         
            +
            You can use custom deserializers by passing a callable object instead of a type name:
         
     | 
| 
      
 639 
     | 
    
         
            +
             
     | 
| 
      
 640 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 641 
     | 
    
         
            +
            COLOR_TO_HEX = lambda do |raw|
         
     | 
| 
      
 642 
     | 
    
         
            +
              case raw
         
     | 
| 
      
 643 
     | 
    
         
            +
              when "red"
         
     | 
| 
      
 644 
     | 
    
         
            +
                "#ff0000"
         
     | 
| 
      
 645 
     | 
    
         
            +
              when "green"
         
     | 
| 
      
 646 
     | 
    
         
            +
                "#00ff00"
         
     | 
| 
      
 647 
     | 
    
         
            +
              when "blue"
         
     | 
| 
      
 648 
     | 
    
         
            +
                "#0000ff"
         
     | 
| 
      
 649 
     | 
    
         
            +
              end
         
     | 
| 
      
 650 
     | 
    
         
            +
            end
         
     | 
| 
      
 651 
     | 
    
         
            +
             
     | 
| 
      
 652 
     | 
    
         
            +
            class CoolConfig < Anyway::Config
         
     | 
| 
      
 653 
     | 
    
         
            +
              attr_config :color
         
     | 
| 
      
 654 
     | 
    
         
            +
             
     | 
| 
      
 655 
     | 
    
         
            +
              coerce_types color: COLOR_TO_HEX
         
     | 
| 
      
 656 
     | 
    
         
            +
            end
         
     | 
| 
      
 657 
     | 
    
         
            +
             
     | 
| 
      
 658 
     | 
    
         
            +
            CoolConfig.new({color: "red"}).color #=> "#ff0000"
         
     | 
| 
      
 659 
     | 
    
         
            +
            ```
         
     | 
| 
      
 660 
     | 
    
         
            +
             
     | 
| 
       492 
661 
     | 
    
         
             
            ## Local files
         
     | 
| 
       493 
662 
     | 
    
         | 
| 
       494 
663 
     | 
    
         
             
            It's useful to have a personal, user-specific configuration in development, which extends the project-wide one.
         
     | 
| 
         @@ -550,7 +719,7 @@ In order to support [source tracing](#tracing), you need to wrap the resulting H 
     | 
|
| 
       550 
719 
     | 
    
         | 
| 
       551 
720 
     | 
    
         
             
            ```ruby
         
     | 
| 
       552 
721 
     | 
    
         
             
            def call(name:, **_opts)
         
     | 
| 
       553 
     | 
    
         
            -
              trace!( 
     | 
| 
      
 722 
     | 
    
         
            +
              trace!(:chamber) do
         
     | 
| 
       554 
723 
     | 
    
         
             
                Chamber.env.to_h[name] || {}
         
     | 
| 
       555 
724 
     | 
    
         
             
              end
         
     | 
| 
       556 
725 
     | 
    
         
             
            end
         
     | 
| 
         @@ -666,7 +835,7 @@ If you want to delete the env var, pass `nil` as the value. 
     | 
|
| 
       666 
835 
     | 
    
         | 
| 
       667 
836 
     | 
    
         
             
            This helper is automatically included to RSpec if `RAILS_ENV` or `RACK_ENV` env variable is equal to "test". It's only available for the example with the tag `type: :config` or with the path `spec/configs/...`.
         
     | 
| 
       668 
837 
     | 
    
         | 
| 
       669 
     | 
    
         
            -
            You can add it manually by requiring `"anyway/testing/helpers"` and including the `Anyway:: 
     | 
| 
      
 838 
     | 
    
         
            +
            You can add it manually by requiring `"anyway/testing/helpers"` and including the `Anyway::Testing::Helpers` module (into RSpec configuration or Minitest test class).
         
     | 
| 
       670 
839 
     | 
    
         | 
| 
       671 
840 
     | 
    
         
             
            ## OptionParser integration
         
     | 
| 
       672 
841 
     | 
    
         | 
| 
         @@ -730,6 +899,62 @@ describe_options( 
     | 
|
| 
       730 
899 
     | 
    
         
             
            )
         
     | 
| 
       731 
900 
     | 
    
         
             
            ```
         
     | 
| 
       732 
901 
     | 
    
         | 
| 
      
 902 
     | 
    
         
            +
            ## RBS support
         
     | 
| 
      
 903 
     | 
    
         
            +
             
     | 
| 
      
 904 
     | 
    
         
            +
            Anyway Config comes with Ruby type signatures (RBS).
         
     | 
| 
      
 905 
     | 
    
         
            +
             
     | 
| 
      
 906 
     | 
    
         
            +
            To use them with Steep, add `library "anyway_config"` to your Steepfile.
         
     | 
| 
      
 907 
     | 
    
         
            +
             
     | 
| 
      
 908 
     | 
    
         
            +
            We also provide an API to generate a type signature for your config class:
         
     | 
| 
      
 909 
     | 
    
         
            +
             
     | 
| 
      
 910 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 911 
     | 
    
         
            +
            class MyGem::Config < Anyway::Config
         
     | 
| 
      
 912 
     | 
    
         
            +
              attr_config :host, port: 8080, tags: [], debug: false
         
     | 
| 
      
 913 
     | 
    
         
            +
             
     | 
| 
      
 914 
     | 
    
         
            +
              coerce_types host: :string, port: :integer,
         
     | 
| 
      
 915 
     | 
    
         
            +
                tags: {type: :string, array: true}
         
     | 
| 
      
 916 
     | 
    
         
            +
             
     | 
| 
      
 917 
     | 
    
         
            +
              required :host
         
     | 
| 
      
 918 
     | 
    
         
            +
            end
         
     | 
| 
      
 919 
     | 
    
         
            +
            ```
         
     | 
| 
      
 920 
     | 
    
         
            +
             
     | 
| 
      
 921 
     | 
    
         
            +
            Then calling `MyGem::Config.to_rbs` will return the following signature:
         
     | 
| 
      
 922 
     | 
    
         
            +
             
     | 
| 
      
 923 
     | 
    
         
            +
            ```rbs
         
     | 
| 
      
 924 
     | 
    
         
            +
            module MyGem
         
     | 
| 
      
 925 
     | 
    
         
            +
              interface _Config
         
     | 
| 
      
 926 
     | 
    
         
            +
                def host: () -> String
         
     | 
| 
      
 927 
     | 
    
         
            +
                def host=: (String) -> void
         
     | 
| 
      
 928 
     | 
    
         
            +
                def port: () -> String?
         
     | 
| 
      
 929 
     | 
    
         
            +
                def port=: (String) -> void
         
     | 
| 
      
 930 
     | 
    
         
            +
                def tags: () -> Array[String]?
         
     | 
| 
      
 931 
     | 
    
         
            +
                def tags=: (Array[String]) -> void
         
     | 
| 
      
 932 
     | 
    
         
            +
                def debug: () -> bool
         
     | 
| 
      
 933 
     | 
    
         
            +
                def debug?: () -> bool
         
     | 
| 
      
 934 
     | 
    
         
            +
                def debug=: (bool) -> void
         
     | 
| 
      
 935 
     | 
    
         
            +
              end
         
     | 
| 
      
 936 
     | 
    
         
            +
             
     | 
| 
      
 937 
     | 
    
         
            +
              class Config < Anyway::Config
         
     | 
| 
      
 938 
     | 
    
         
            +
                include _Config
         
     | 
| 
      
 939 
     | 
    
         
            +
              end
         
     | 
| 
      
 940 
     | 
    
         
            +
            end
         
     | 
| 
      
 941 
     | 
    
         
            +
            ```
         
     | 
| 
      
 942 
     | 
    
         
            +
             
     | 
| 
      
 943 
     | 
    
         
            +
            ### Handling `on_load`
         
     | 
| 
      
 944 
     | 
    
         
            +
             
     | 
| 
      
 945 
     | 
    
         
            +
            When we use `on_load` callback with a block, we switch the context (via `instance_eval`), and we need to provide type hints for the type checker. Here is an example:
         
     | 
| 
      
 946 
     | 
    
         
            +
             
     | 
| 
      
 947 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 948 
     | 
    
         
            +
            class MyConfig < Anyway::Config
         
     | 
| 
      
 949 
     | 
    
         
            +
              on_load do
         
     | 
| 
      
 950 
     | 
    
         
            +
                # @type self : MyConfig
         
     | 
| 
      
 951 
     | 
    
         
            +
                raise_validation_error("host is invalid") if host.start_with?("localhost")
         
     | 
| 
      
 952 
     | 
    
         
            +
              end
         
     | 
| 
      
 953 
     | 
    
         
            +
            end
         
     | 
| 
      
 954 
     | 
    
         
            +
            ```
         
     | 
| 
      
 955 
     | 
    
         
            +
             
     | 
| 
      
 956 
     | 
    
         
            +
            Yeah, a lot of annotations 😞 Welcome to the type-safe world!
         
     | 
| 
      
 957 
     | 
    
         
            +
             
     | 
| 
       733 
958 
     | 
    
         
             
            ## Contributing
         
     | 
| 
       734 
959 
     | 
    
         | 
| 
       735 
960 
     | 
    
         
             
            Bug reports and pull requests are welcome on GitHub at [https://github.com/palkan/anyway_config](https://github.com/palkan/anyway_config).
         
     |