Config Ruby Gem

repository·master·Indexed 24 days ago

https://github.com/rubyconfig/config

A Ruby gem for managing environment-specific settings using YAML files. It supports inheritance, ERB evaluation, and object member notation for accessing settings. Config integrates with Rails, Padrino, and Sinatra, and provides features for environment variable overrides, runtime reloading, and configuration validation using dry-schema or dry-validation.

Tokens
7K
Snippets
17
Records
41
Agent score
79%

What's inside rubyconfig-config

  1. Use Embedded Ruby (ERB) in YAML config files

    master

    Config supports ERB within YAML files. This allows you to use dynamic values (like environment variables or computed logic) inside your configuration. ERB is evaluated at load time if evaluate_erb_in_yaml is set to true in the configuration.

    # config/environments/development.yml
    size: 2
    computed: <%= 1 + 2 + 3 %>
    section:
      size: 3
      servers: [ {name: yahoo.com}, {name: amazon.com} ]

    Accessing the computed values:

    Settings.computed # => 6
    Settings.section.size # => 3
    Settings.section.servers[0].name # => "yahoo.com"
  2. Configure the Config gem

    master

    You can customize the Config object once, preferably during the application initialization phase, using the Config.setup block. This allows you to change the name of the constant that holds your settings and other global behaviors.

    Config.setup do |config|
      config.const_name = 'Settings'
      # ...
    end
  3. Handle missing keys with fail_on_missing

    master

    By default, accessing a non-existent key returns nil. To prevent typos and ensure all required keys are present, you can enable fail_on_missing. This causes the application to raise a KeyError when an undefined key is accessed.

    Config.setup do |config|
      config.fail_on_missing = true
    end
    
    # If :path is not defined in any config file:
    Settings.path # => raises KeyError: key not found: :path
    Config.setup do |config|
      config.fail_on_missing = true
    end
  4. Validate configuration with dry-schema or dry-validation

    master

    You can ensure your configuration values meet specific requirements (presence, type, or complex rules) by providing a schema or a validation_contract. If validation fails, a Config::Validation::Error is raised.

    Using a Contract (dry-validation)

    Use config.validation_contract to define complex rules and dependencies between fields.

    class ConfigContract < Dry::Validation::Contract
      params do
        optional(:email).maybe(:str?)
    
        required(:youtube).schema do
          required(:api_key).filled
        end
      end
    
      rule(:email) do
        unless /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i.match?(value)
          key.failure('has invalid format')
        end
      end
    end
    
    Config.setup do |config|
      config.validation_contract = ConfigContract.new
    end

    Using a Schema (dry-schema)

    Use config.schema for simpler type and presence validation.

    Config.setup do |config|
      # ...
      config.schema do
        optional(:email).maybe(:str?)
    
        required(:youtube).schema do
          required(:api_key).filled
        end
      end
    end
  5. Install Config on other Ruby projects

    master

    For non-framework Ruby projects, add the gem to your Gemfile and initialize Config manually.

    You can provide a config root and the current environment:

    Config.load_and_set_settings(Config.setting_files("/path/to/config_root", "your_project_environment"))

    Alternatively, you can pass specific YAML paths directly:

    Config.load_and_set_settings("/path/to/yaml1", "/path/to/yaml2", ...)
  6. Load settings from AWS Secrets Manager

    master

    You can treat secrets from AWS Secrets Manager as environment variables by using Config::Sources::EnvSource. This involves fetching the secret, parsing the JSON, and adding it as a new source.

    # fetch secrets from AWS
    client = Aws::SecretsManager::Client.new
    response = client.get_secret_value(secret_id: "#{ENV['ENVIRONMENT']}/my_application")
    secrets = JSON.parse(response.secret_string)
    
    # load secrets into config
    secret_source = Config::Sources::EnvSource.new(secrets)
    Settings.add_source!(secret_source)
    Settings.reload!

    EnvSource accepts optional overrides for prefix, separator, converter, and parse_values in its constructor.

  7. Install Config on Rails

    master

    To install Config in a Rails application:

    1. Add gem 'config' to your Gemfile and run bundle install.
    2. Run the generator command: rails g config:install

    This generates config/initializers/config.rb and a set of default settings files:

    • config/settings.yml
    • config/settings.local.yml
    • config/settings/development.yml
    • config/settings/production.yml
    • config/settings/test.yml

    By default, the config environment matches Rails.env. You can override this by setting config.environment in the initializer.

    rails g config:install
  8. Work with environment variables

    master

    To allow environment variables to override file-based settings, set use_env = true in your configuration. The gem will look for environment variables that match your const_name and follow the hierarchy defined by env_prefix and env_separator.

    Configuration Example

    If you want to use SETTINGS__SECTION__SERVER to map to Settings.section.server:

    Config.setup do |config|
      config.const_name = 'Settings'
      config.use_env = true
      config.env_prefix = 'SETTINGS'
      config.env_separator = '__'
      config.env_converter = :downcase
      config.env_parse_values = true
    end

    Environment Variable Mapping

    Given the environment:

    SETTINGS__SECTION__SERVER_SIZE=1
    SETTINGS__SECTION__SERVER=google.com
    SETTINGS__SECTION__SSL_ENABLED=false

    The settings will be:

    Settings.section.server_size # => 1
    Settings.section.server # => 'google.com'
    Settings.section.ssl_enabled # => false

    Note: Environment variables cannot be used to assign arrays. Also, avoid using environment variables to simultaneously assign a 'flat' value and a multi-level value to the same key (e.g., setting both BACKEND_DATABASE and BACKEND_DATABASE_USER).

    Config.setup do |config|
      config.use_env = true
      config.env_prefix = 'SETTINGS'
      config.env_separator = '__'
      config.env_converter = :downcase
      config.env_parse_values = true
    end
  9. Access configuration using dot notation or bracket notation

    master

    The Config::Options class allows for flexible property access. You can use standard dot notation (e.g., settings.foo) or bracket notation (e.g., settings['foo']).

    Note that certain reserved names are handled specially to avoid conflicts with OpenStruct or Rails 7.*. For these names, bracket notation is preferred or required to access the underlying value.

    Reserved Names:

    • SETTINGS_RESERVED_NAMES: select, collect, test, count, zip, min, max, exit!, table
    • RAILS_RESERVED_NAMES: maximum, minimum
  10. Reload settings in development mode

    master
    In a Rails development environment, the config gem automatically reloads your settings on every request. This is achieved by prepending a before_action (or before_filter in older Rails versions) to ActionController::Base that calls Config.reload!. This allows you to modify your configuration files and see the changes reflected in your application immediately without needing to restart the Rails server.