Module: Canon::Config::ConfigDSL
- Included in:
- DiffConfig
- Defined in:
- lib/canon/config/config_dsl.rb
Overview
DSL for declaring config-backed attributes on a config class.
A config class (DiffConfig, MatchConfig, FormatConfig) extends this module and declares each user-tunable attribute with #config_key. The DSL generates the matching getter/setter pair and registers the attribute’s metadata (type, enum, default, coercion) in a per-class registry so other components (EnvSchema, TypeConverter) can discover it without duplicating the schema.
Goals (lutaml/canon TODO.improve/07):
-
Eliminate the 5-line getter/setter boilerplate per attribute
-
Provide a single source of truth for attribute types/enums
-
Keep the public API stable (methods behave exactly as before)
Instance Method Summary collapse
-
#config_key(name, type: :pass_through, enum: nil, default: nil, coerce: nil, getter_coerce: nil) ⇒ void
Declare a config-backed attribute.
-
#config_keys ⇒ Object
Per-class attribute registry, lazily initialized on first
config_keydeclaration. -
#enum_values ⇒ Hash{Symbol => Array}
Enum constraint map, keyed by attribute name.
-
#resolve_default(key) ⇒ Object
Resolve a declared default to a concrete value.
-
#validate_config_value!(key, value) ⇒ void
Validate a value against an attribute’s enum, if any.
Instance Method Details
#config_key(name, type: :pass_through, enum: nil, default: nil, coerce: nil, getter_coerce: nil) ⇒ void
This method returns an undefined value.
Declare a config-backed attribute.
Generates a getter and setter on the extending class. The getter reads through the resolver; the setter validates against enum (if provided), applies coerce (if provided), and writes through the resolver.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/canon/config/config_dsl.rb', line 63 def config_key(name, type: :pass_through, enum: nil, default: nil, coerce: nil, getter_coerce: nil) sym = name.to_sym config_keys[sym] = { type: type, enum: enum, default: default, default_proc: default.is_a?(Proc) ? default : nil, coerce: coerce, getter_coerce: getter_coerce, }.freeze define_getter(sym, getter_coerce) define_setter(sym, coerce) end |
#config_keys ⇒ Object
Per-class attribute registry, lazily initialized on first config_key declaration. Stored on the extending class so each config class owns its own map without registry leakage.
39 40 41 |
# File 'lib/canon/config/config_dsl.rb', line 39 def config_keys @config_keys ||= {} end |
#enum_values ⇒ Hash{Symbol => Array}
Enum constraint map, keyed by attribute name.
Derived from declared config_keys for backward compatibility with the original VALID_ENUM_VALUES constant.
123 124 125 |
# File 'lib/canon/config/config_dsl.rb', line 123 def enum_values config_keys.filter_map { |k, m| [k, m[:enum]] if m[:enum] }.to_h end |
#resolve_default(key) ⇒ Object
Resolve a declared default to a concrete value.
If the declared default is a callable (e.g. a proc or method object), it is invoked each time this method is called so the result reflects the current runtime state. Otherwise the stored default value is returned as-is.
88 89 90 91 92 93 94 95 96 |
# File 'lib/canon/config/config_dsl.rb', line 88 def resolve_default(key) = config_keys[key] return nil unless proc_form = [:default_proc] return proc_form.call if proc_form [:default] end |
#validate_config_value!(key, value) ⇒ void
This method returns an undefined value.
Validate a value against an attribute’s enum, if any.
Mirrors the original DiffConfig.validate_config_value! API so existing call sites (and specs) keep working.
107 108 109 110 111 112 113 114 115 |
# File 'lib/canon/config/config_dsl.rb', line 107 def validate_config_value!(key, value) = config_keys[key] return unless &.dig(:enum) return if [:enum].include?(value) raise ArgumentError, "Invalid value #{value.inspect} for #{key}. " \ "Valid values: #{[:enum].map(&:inspect).join(', ')}" end |