Class: MywayConfig::Base
- Inherits:
-
Anyway::Config
- Object
- Anyway::Config
- MywayConfig::Base
- Defined in:
- lib/myway_config/base.rb
Overview
Base configuration class that extends Anyway::Config with additional features
Provides:
- ConfigSection coercion for nested configuration
- XDG config file loading
- Bundled defaults loading with environment overrides
- Environment detection helpers
- Deep merge utilities
Class Method Summary collapse
-
.auto_configure! ⇒ Object
Auto-configure attributes and coercions from the YAML schema.
-
.boolean?(value) ⇒ Boolean
Check if a value is a boolean.
-
.config_section ⇒ Proc
Simple ConfigSection coercion without schema defaults.
-
.config_section_coercion(section_key) ⇒ Proc
Create a coercion that merges incoming value with schema defaults for a section.
-
.deep_merge_hashes(base, overlay) ⇒ Hash
Deep merge helper for coercion.
-
.defaults_path(path = nil) ⇒ Object
Register a defaults file path for this config class.
-
.define_environment_predicates ⇒ Array<Symbol>
Define predicate methods for each environment in the config.
-
.env ⇒ String
Get the current environment.
-
.schema ⇒ Hash
Load and cache the schema from defaults file.
-
.to_boolean ⇒ Proc
Boolean coercion helper.
-
.to_symbol ⇒ Proc
Symbol coercion helper.
-
.valid_environment? ⇒ Boolean
Check if current environment is valid.
-
.valid_environments ⇒ Array<Symbol>
Returns list of valid environment names from bundled defaults.
-
.validate_environment! ⇒ void
Validate that the current environment is defined in the config.
Instance Method Summary collapse
-
#environment ⇒ String
Get the current environment name.
-
#initialize(source = nil) ⇒ Base
constructor
Initialize configuration from defaults, a file path, or a Hash.
-
#valid_environment? ⇒ Boolean
Check if environment is valid.
Constructor Details
#initialize(source = nil) ⇒ Base
Initialize configuration from defaults, a file path, or a Hash
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/myway_config/base.rb', line 263 def initialize(source = nil) overrides = case source when String, Pathname load_from_file(source.to_s) when Hash source when nil nil else raise ConfigurationError, "Invalid source: expected String, Pathname, Hash, or nil" end self.class.validate_environment! super(overrides) end |
Class Method Details
.auto_configure! ⇒ Object
Auto-configure attributes and coercions from the YAML schema
This method reads the defaults section from the YAML file and automatically generates attr_config declarations and coercions. Hash values become ConfigSection objects with method-style access.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/myway_config/base.rb', line 197 def auto_configure! raise ConfigurationError, 'defaults_path must be set before auto_configure!' unless @defaults_path coercions = {} schema.each do |key, value| # Don't pass defaults to attr_config - they come from bundled_defaults loader # Passing defaults here would cause them to be applied AFTER env vars attr_config key coercions[key] = if value.is_a?(Hash) config_section_coercion(key) elsif value.is_a?(Symbol) to_symbol elsif boolean?(value) to_boolean end end coerce_types(coercions.compact) define_environment_predicates validate_environment! end |
.boolean?(value) ⇒ Boolean
Check if a value is a boolean
225 226 227 |
# File 'lib/myway_config/base.rb', line 225 def boolean?(value) value.is_a?(TrueClass) || value.is_a?(FalseClass) end |
.config_section ⇒ Proc
Simple ConfigSection coercion without schema defaults
94 95 96 97 98 99 |
# File 'lib/myway_config/base.rb', line 94 def config_section ->(v) { return v if v.is_a?(MywayConfig::ConfigSection) MywayConfig::ConfigSection.new(v || {}) } end |
.config_section_coercion(section_key) ⇒ Proc
Create a coercion that merges incoming value with schema defaults for a section
This ensures environment variables don't lose other defaults.
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/myway_config/base.rb', line 79 def config_section_coercion(section_key) defaults = schema[section_key] || {} ->(v) { return v if v.is_a?(MywayConfig::ConfigSection) incoming = v || {} # Deep merge: defaults first, then overlay incoming values merged = deep_merge_hashes(defaults.dup, incoming) MywayConfig::ConfigSection.new(merged) } end |
.deep_merge_hashes(base, overlay) ⇒ Hash
Deep merge helper for coercion
130 131 132 133 134 135 136 137 138 |
# File 'lib/myway_config/base.rb', line 130 def deep_merge_hashes(base, ) base.merge() do |_key, old_val, new_val| if old_val.is_a?(Hash) && new_val.is_a?(Hash) deep_merge_hashes(old_val, new_val) else new_val.nil? ? old_val : new_val end end end |
.defaults_path(path = nil) ⇒ Object
Register a defaults file path for this config class
45 46 47 48 49 50 51 52 53 |
# File 'lib/myway_config/base.rb', line 45 def defaults_path(path = nil) if path raise ConfigurationError, "Defaults file not found: #{path}" unless File.exist?(path) @defaults_path = path # Register with the loader MywayConfig::Loaders::DefaultsLoader.register(config_name, path) end @defaults_path end |
.define_environment_predicates ⇒ Array<Symbol>
Define predicate methods for each environment in the config
Generates instance methods like development?, production?, staging?
based on the environment names found in the YAML config file.
173 174 175 176 177 178 179 180 181 |
# File 'lib/myway_config/base.rb', line 173 def define_environment_predicates valid_environments.map do |env_name| method_name = "#{env_name}?" define_method(method_name) do self.class.env == env_name.to_s end method_name.to_sym end end |
.env ⇒ String
Get the current environment
Override this method to customize environment detection. Default priority: RAILS_ENV > RACK_ENV > 'development'
146 147 148 149 150 151 |
# File 'lib/myway_config/base.rb', line 146 def env Anyway::Settings.current_environment || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development' end |
.schema ⇒ Hash
Load and cache the schema from defaults file
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/myway_config/base.rb', line 58 def schema @schema ||= begin return {} unless @defaults_path && File.exist?(@defaults_path) content = File.read(@defaults_path) raw = YAML.safe_load( content, permitted_classes: [Symbol], symbolize_names: true, aliases: true ) || {} raw[:defaults] || {} end end |
.to_boolean ⇒ Proc
Boolean coercion helper
Converts string values "true"/"false" to actual booleans. This is needed for environment variable values.
114 115 116 117 118 119 120 121 122 123 |
# File 'lib/myway_config/base.rb', line 114 def to_boolean ->(v) { case v when TrueClass, FalseClass then v when String then v.downcase == 'true' when nil then false else !!v end } end |
.to_symbol ⇒ Proc
Symbol coercion helper
104 105 106 |
# File 'lib/myway_config/base.rb', line 104 def to_symbol ->(v) { v.nil? ? nil : v.to_s.to_sym } end |
.valid_environment? ⇒ Boolean
Check if current environment is valid
163 164 165 |
# File 'lib/myway_config/base.rb', line 163 def valid_environment? MywayConfig::Loaders::DefaultsLoader.valid_environment?(config_name, env) end |
.valid_environments ⇒ Array<Symbol>
Returns list of valid environment names from bundled defaults
156 157 158 |
# File 'lib/myway_config/base.rb', line 156 def valid_environments MywayConfig::Loaders::DefaultsLoader.valid_environments(config_name) end |
.validate_environment! ⇒ void
This method returns an undefined value.
Validate that the current environment is defined in the config
233 234 235 236 237 238 239 |
# File 'lib/myway_config/base.rb', line 233 def validate_environment! return unless @defaults_path return if valid_environment? raise ConfigurationError, "Invalid environment '#{env}'. Valid environments: #{valid_environments.join(', ')}" end |
Instance Method Details
#environment ⇒ String
Get the current environment name
309 310 311 |
# File 'lib/myway_config/base.rb', line 309 def environment self.class.env end |
#valid_environment? ⇒ Boolean
Check if environment is valid
316 317 318 |
# File 'lib/myway_config/base.rb', line 316 def valid_environment? self.class.valid_environment? end |