dry-configurable

repository·main·Indexed 19 days ago

https://github.com/dry-rb/dry-configurable

A Ruby gem providing a lightweight and flexible way to define and manage configuration settings for Ruby objects or classes. It supports both class-level configuration via `extend Dry::Configurable` and instance-level configuration via `include Dry::Configurable`. Key features include nested settings, default values, value transformation via constructors, and the ability to finalize configurations for immutability or convert them into Data objects for performance.

Tokens
3.5K
Snippets
20
Records
23
Agent score
65%

What's inside dry-configurable

  1. Understand the properties of a Setting

    main

    In dry-configurable, a Setting represents a single configuration entry. Each setting is defined by several key attributes that control how its value is stored, accessed, and transformed:

    • name: The identifier for the setting.
    • default: The initial value assigned to the setting.
    • constructor: A proc or object used to transform the value (e.g., for type coercion).
    • children: A collection of nested settings, making this setting a configuration group.
    • mutable: A boolean indicating if the value can be modified in place. If a setting has children, it is automatically considered mutable.
    • options: Additional metadata passed during definition.

    Note that cloneable? is an alias for mutable?.

  2. Difference between extending and including Dry::Configurable

    main

    How you integrate Dry::Configurable determines where the configuration methods reside:

    1. Extending (extend Dry::Configurable): Provides class-level configuration. You can define settings on the class itself and access them via MyClass.config or MyClass.setting.
    2. Including (include Dry::Configurable): Provides instance-level configuration. The class-level config method is undefined; instead, configuration is managed on individual instances of the class.
  3. Configure classes using Dry::Configurable

    main

    You can add configuration capabilities to a Ruby class by either extending or including Dry::Configurable.

    • Class-level configuration: Use extend Dry::Configurable to define settings that are shared across the class. These settings are accessed via YourClass.config.
    • Instance-level configuration: Use include Dry::Configurable to define settings that are unique to each instance of the class. These settings are accessed via your_instance.config.

    Use the setting method to define configuration keys. You can also nest settings by providing a block to setting.

    # Class-level configuration
    class App
      extend Dry::Configurable
    
      setting :database do
        setting :dsn, 'sqlite:memory'
      end
    end
    
    App.config.database.dsn = 'jdbc:sqlite:memory'
    puts App.config.database.dsn # => "jdbc:sqlite:memory"
    
    # Instance-level configuration
    class App
      include Dry::Configurable
    
      setting :database
    end
    
    production = App.new
    production.config.database = ENV['DATABASE_URL']
    production.finalize!
    
    development = App.new
    development.config.database = 'jdbc:sqlite:memory'
    development.finalize!
  4. Troubleshoot Dry::Configurable errors

    main

    When using dry-configurable, you may encounter specific error classes if the configuration state or inclusion logic is violated.

    • Dry::Configurable::FrozenConfigError: Raised when attempting to modify a configuration that has already been frozen.
    • Dry::Configurable::AlreadyIncludedError: Raised if include Dry::Configurable is called more than once on the same class (note: this constant is deprecated in favor of standard Ruby behavior or internal handling, but may still appear in legacy contexts).
  5. Finalize and freeze configuration with `finalize!`

    main

    The finalize! method is used to prepare the configuration for use, typically by resolving any dynamic settings and optionally freezing the configuration to prevent further modifications.

    Use the freeze_values: keyword argument to determine if the individual values within the configuration should also be frozen.

    • freeze_values: true: Freezes the configuration object and all its contained values.
    • freeze_values: false (default): Freezes the configuration object but not necessarily the values themselves.
    # Finalize and freeze the configuration to prevent further changes
    MyClass.finalize!(freeze_values: true)
  6. Configure settings with `configure`

    main

    The configure method allows you to modify the configuration object of a class or instance. It yields the configuration object to a block, where you can set various settings. If the configuration has already been frozen (e.g., via finalize!), calling configure will raise a Dry::Configurable::FrozenConfigError.

    # Assuming a class has included Dry::Configurable
    MyClass.configure do |config|
      config.some_setting = 'value'
    end
  7. Finalize instance configuration

    main

    When using instance-level configuration (include Dry::Configurable), call finalize! on the instance after setting its configuration values. This ensures the configuration state is locked or prepared for use according to the internal lifecycle of the object.

    app = App.new
    app.config.database = 'sqlite:memory'
    app.finalize!
  8. Convert configuration to a Hash

    main

    You can retrieve the current configuration values as a Hash using the values method or to_h.

    • values: Returns a Hash where nested configurations remain as Dry::Configurable::Config instances.
    • to_h: Returns a Hash where nested configurations are recursively converted into standard Hashes.
    # Returns Hash with nested Config objects
    hash_with_configs = config.values
    
    # Returns Hash with nested Hashes
    hash_with_hashes = config.to_h