myway_config 0.1.1

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.
@@ -0,0 +1,220 @@
1
+ # Hash-like Behavior
2
+
3
+ ConfigSection provides Hash-like access and Enumerable support.
4
+
5
+ ## What is ConfigSection?
6
+
7
+ When you define a nested configuration in YAML:
8
+
9
+ ```yaml
10
+ defaults:
11
+ database:
12
+ host: localhost
13
+ port: 5432
14
+ ```
15
+
16
+ The `database` value becomes a `ConfigSection` object, not a plain Hash:
17
+
18
+ ```ruby
19
+ config.database.class # => MywayConfig::ConfigSection
20
+ ```
21
+
22
+ ## Why ConfigSection?
23
+
24
+ ConfigSection provides:
25
+
26
+ 1. **Method access** - `config.database.host` instead of `config.database[:host]`
27
+ 2. **Multiple access patterns** - Methods, symbols, and strings all work
28
+ 3. **Hash-like enumeration** - `Enumerable` methods like `map`, `select`, `find`
29
+ 4. **Safe nested access** - `dig` for deep traversal
30
+
31
+ ## Access Methods
32
+
33
+ ### Method Syntax
34
+
35
+ ```ruby
36
+ config.database.host # => "localhost"
37
+ ```
38
+
39
+ ### Bracket Syntax
40
+
41
+ ```ruby
42
+ config.database[:host] # => "localhost"
43
+ config.database["host"] # => "localhost"
44
+ ```
45
+
46
+ ### Setting Values
47
+
48
+ ```ruby
49
+ config.database.host = "new-host"
50
+ config.database[:port] = 5433
51
+ ```
52
+
53
+ ## Hash Methods
54
+
55
+ ### Keys and Values
56
+
57
+ ```ruby
58
+ config.database.keys # => [:host, :port, :name, :pool]
59
+ config.database.values # => ["localhost", 5432, "myapp_db", 5]
60
+ config.database.size # => 4
61
+ config.database.length # => 4
62
+ ```
63
+
64
+ ### Key Checking
65
+
66
+ ```ruby
67
+ config.database.key?(:host) # => true
68
+ config.database.has_key?(:host) # => true
69
+ config.database.include?(:host) # => true
70
+ config.database.member?(:host) # => true
71
+
72
+ config.database.empty? # => false
73
+ ```
74
+
75
+ ### Fetch
76
+
77
+ ```ruby
78
+ # With key
79
+ config.database.fetch(:host) # => "localhost"
80
+
81
+ # With default
82
+ config.database.fetch(:missing, "default") # => "default"
83
+
84
+ # With block
85
+ config.database.fetch(:missing) { |k| "no #{k}" } # => "no missing"
86
+
87
+ # Without default (raises KeyError)
88
+ config.database.fetch(:missing) # => KeyError: key not found: :missing
89
+ ```
90
+
91
+ ### Dig
92
+
93
+ ```ruby
94
+ config.api.dig(:headers, :content_type) # => "application/json"
95
+ config.api.dig(:missing, :nested) # => nil
96
+ ```
97
+
98
+ ## Enumerable Methods
99
+
100
+ ConfigSection includes `Enumerable`:
101
+
102
+ ### each
103
+
104
+ ```ruby
105
+ config.database.each do |key, value|
106
+ puts "#{key}: #{value}"
107
+ end
108
+ # host: localhost
109
+ # port: 5432
110
+ # ...
111
+ ```
112
+
113
+ ### map
114
+
115
+ ```ruby
116
+ config.database.map { |k, v| "#{k}=#{v}" }
117
+ # => ["host=localhost", "port=5432", ...]
118
+ ```
119
+
120
+ ### select / reject
121
+
122
+ ```ruby
123
+ # Select numeric values
124
+ config.database.select { |k, v| v.is_a?(Integer) }
125
+ # => [[:port, 5432], [:pool, 5]]
126
+
127
+ # Reject nil values
128
+ config.database.reject { |k, v| v.nil? }
129
+ ```
130
+
131
+ ### find / detect
132
+
133
+ ```ruby
134
+ config.database.find { |k, v| v == 5432 }
135
+ # => [:port, 5432]
136
+ ```
137
+
138
+ ### any? / all? / none?
139
+
140
+ ```ruby
141
+ config.database.any? { |k, v| v.nil? } # => false
142
+ config.database.all? { |k, v| v } # => true
143
+ config.database.none? { |k, v| v.nil? } # => true
144
+ ```
145
+
146
+ ### Other Enumerable Methods
147
+
148
+ All standard Enumerable methods work:
149
+
150
+ - `count`, `first`, `take`, `drop`
151
+ - `min`, `max`, `minmax`
152
+ - `sort`, `sort_by`
153
+ - `group_by`, `partition`
154
+ - `reduce`, `inject`
155
+ - And more...
156
+
157
+ ## Conversion
158
+
159
+ ### to_h
160
+
161
+ Convert to a plain Ruby Hash:
162
+
163
+ ```ruby
164
+ config.database.to_h
165
+ # => {host: "localhost", port: 5432, name: "myapp_db", pool: 5}
166
+ ```
167
+
168
+ Nested ConfigSections are also converted:
169
+
170
+ ```ruby
171
+ config.api.to_h
172
+ # => {
173
+ # base_url: "https://api.example.com",
174
+ # timeout: 30,
175
+ # headers: {content_type: "application/json"}
176
+ # }
177
+ ```
178
+
179
+ ### merge
180
+
181
+ Merge with another ConfigSection or Hash:
182
+
183
+ ```ruby
184
+ overrides = { host: "new-host", pool: 10 }
185
+ merged = config.database.merge(overrides)
186
+
187
+ merged.host # => "new-host"
188
+ merged.pool # => 10
189
+ merged.port # => 5432 (from original)
190
+ ```
191
+
192
+ ## Practical Examples
193
+
194
+ ### Building Connection Strings
195
+
196
+ ```ruby
197
+ db = config.database
198
+ connection_string = "postgres://#{db.host}:#{db.port}/#{db.name}"
199
+ ```
200
+
201
+ ### Filtering Configuration
202
+
203
+ ```ruby
204
+ # Get all non-nil database settings
205
+ config.database.reject { |k, v| v.nil? }.to_h
206
+ ```
207
+
208
+ ### Transforming Values
209
+
210
+ ```ruby
211
+ # Upcase all string values
212
+ config.database.map { |k, v|
213
+ [k, v.is_a?(String) ? v.upcase : v]
214
+ }.to_h
215
+ ```
216
+
217
+ ## Next Steps
218
+
219
+ - [Examples](../examples/index.md) - Real-world usage examples
220
+ - [API Reference](../api/config-section.md) - Complete ConfigSection API
@@ -0,0 +1,15 @@
1
+ # Guides
2
+
3
+ These guides cover MywayConfig features in depth.
4
+
5
+ ## Core Concepts
6
+
7
+ - [Defining Configuration](defining-configuration.md) - How to create config classes
8
+ - [YAML Structure](yaml-structure.md) - Understanding the defaults file format
9
+ - [Accessing Values](accessing-values.md) - All the ways to read configuration
10
+
11
+ ## Advanced Topics
12
+
13
+ - [Environment Overrides](environment-overrides.md) - Using environment variables
14
+ - [Custom File Loading](custom-file-loading.md) - Loading from non-standard locations
15
+ - [Hash-like Behavior](hash-like-behavior.md) - Using ConfigSection as a Hash
@@ -0,0 +1,168 @@
1
+ # YAML Structure
2
+
3
+ The YAML defaults file is the single source of truth for your configuration structure and default values.
4
+
5
+ ## Required Structure
6
+
7
+ The file must have a `defaults` key. Other top-level keys are environment names.
8
+
9
+ ```yaml
10
+ defaults: # Required - defines structure and default values
11
+ key: value
12
+
13
+ development: # Optional - overrides for development
14
+ key: dev_value
15
+
16
+ production: # Optional - overrides for production
17
+ key: prod_value
18
+
19
+ test: # Optional - overrides for test
20
+ key: test_value
21
+ ```
22
+
23
+ ## The `defaults` Section
24
+
25
+ The `defaults` section defines:
26
+
27
+ 1. **Structure** - What keys exist in your configuration
28
+ 2. **Types** - Hash values become `ConfigSection`, symbols stay symbols
29
+ 3. **Default values** - Base values before any overrides
30
+
31
+ ```yaml
32
+ defaults:
33
+ # Nested configuration (becomes ConfigSection)
34
+ database:
35
+ host: localhost
36
+ port: 5432
37
+ name: myapp_db
38
+ pool: 5
39
+
40
+ # Another nested section
41
+ api:
42
+ base_url: https://api.example.com
43
+ timeout: 30
44
+ headers:
45
+ content_type: application/json
46
+
47
+ # Symbol value (coerced to :info)
48
+ log_level: :info
49
+
50
+ # Scalar values
51
+ debug: false
52
+ max_connections: 10
53
+ ```
54
+
55
+ ## Environment Sections
56
+
57
+ Environment sections contain only overrides. Values merge with defaults.
58
+
59
+ ```yaml
60
+ defaults:
61
+ database:
62
+ host: localhost
63
+ port: 5432
64
+ name: myapp_db
65
+ log_level: :info
66
+ debug: false
67
+
68
+ development:
69
+ # Only override what's different
70
+ database:
71
+ name: myapp_development
72
+ log_level: :debug
73
+ debug: true
74
+
75
+ production:
76
+ database:
77
+ host: prod-db.example.com
78
+ name: myapp_production
79
+ pool: 25
80
+ log_level: :warn
81
+ # debug remains false (from defaults)
82
+
83
+ test:
84
+ database:
85
+ name: myapp_test
86
+ ```
87
+
88
+ ## Merge Behavior
89
+
90
+ Environment values are deep-merged with defaults:
91
+
92
+ ```yaml
93
+ defaults:
94
+ database:
95
+ host: localhost
96
+ port: 5432
97
+ name: myapp_db
98
+ pool: 5
99
+
100
+ production:
101
+ database:
102
+ host: prod-db.example.com
103
+ pool: 25
104
+ ```
105
+
106
+ Result in production:
107
+
108
+ ```ruby
109
+ config.database.host # => "prod-db.example.com" (overridden)
110
+ config.database.port # => 5432 (from defaults)
111
+ config.database.name # => "myapp_db" (from defaults)
112
+ config.database.pool # => 25 (overridden)
113
+ ```
114
+
115
+ ## Supported Value Types
116
+
117
+ | YAML Type | Ruby Type | Notes |
118
+ |-----------|-----------|-------|
119
+ | `string` | `String` | Plain strings |
120
+ | `123` | `Integer` | Numbers |
121
+ | `1.5` | `Float` | Decimals |
122
+ | `true`/`false` | `Boolean` | Booleans |
123
+ | `:symbol` | `Symbol` | Colon prefix for symbols |
124
+ | `hash:` | `ConfigSection` | Nested hashes become ConfigSection |
125
+ | `[a, b]` | `Array` | Arrays |
126
+ | `null` | `nil` | Null values |
127
+
128
+ ## Environment Detection
129
+
130
+ The current environment is determined by (in order):
131
+
132
+ 1. `Anyway::Settings.current_environment`
133
+ 2. `ENV['RAILS_ENV']`
134
+ 3. `ENV['RACK_ENV']`
135
+ 4. `'development'` (default)
136
+
137
+ ## Custom Environments
138
+
139
+ You can define any environment name:
140
+
141
+ ```yaml
142
+ defaults:
143
+ api_url: https://api.example.com
144
+
145
+ staging:
146
+ api_url: https://staging-api.example.com
147
+
148
+ canary:
149
+ api_url: https://canary-api.example.com
150
+ ```
151
+
152
+ ```bash
153
+ RACK_ENV=staging ruby app.rb
154
+ ```
155
+
156
+ ## Valid Environments
157
+
158
+ You can check if an environment is defined:
159
+
160
+ ```ruby
161
+ MyApp::Config.valid_environments # => [:development, :production, :test]
162
+ MyApp::Config.valid_environment? # => true (if current env is defined)
163
+ ```
164
+
165
+ ## Next Steps
166
+
167
+ - [Accessing Values](accessing-values.md) - How to read your configuration
168
+ - [Environment Overrides](environment-overrides.md) - Override with environment variables
data/docs/index.md ADDED
@@ -0,0 +1,86 @@
1
+ # MywayConfig
2
+
3
+ **Configuration management for Ruby applications with XDG support and auto-configuration from YAML.**
4
+
5
+ MywayConfig extends [anyway_config](https://github.com/palkan/anyway_config) with:
6
+
7
+ - **XDG config file loading** - Respects `~/.config/<app>/config.yml`
8
+ - **Bundled defaults** - Ship defaults with your gem
9
+ - **Auto-configuration** - Define structure once in YAML, access everywhere
10
+ - **Hash-like behavior** - `Enumerable` support for config sections
11
+
12
+ ## Features
13
+
14
+ ```yaml
15
+ # Define once in YAML
16
+ defaults:
17
+ database:
18
+ host: localhost
19
+ port: 5432
20
+ log_level: :info
21
+
22
+ production:
23
+ database:
24
+ host: prod-db.example.com
25
+ ```
26
+
27
+ ```ruby
28
+ # Access with clean Ruby syntax
29
+ config.database.host # => "localhost"
30
+ config.database[:host] # => "localhost"
31
+ config.database['host'] # => "localhost"
32
+ config.log_level # => :info
33
+ ```
34
+
35
+ ## Quick Example
36
+
37
+ ```ruby
38
+ require "myway_config"
39
+
40
+ module MyApp
41
+ class Config < MywayConfig::Base
42
+ config_name :myapp
43
+ env_prefix :myapp
44
+ defaults_path File.expand_path("config/defaults.yml", __dir__)
45
+ auto_configure!
46
+ end
47
+
48
+ def self.config
49
+ @config ||= Config.new
50
+ end
51
+ end
52
+
53
+ # Use it
54
+ MyApp.config.database.host
55
+ MyApp.config.production?
56
+ ```
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ gem install myway_config
62
+ ```
63
+
64
+ Or add to your Gemfile:
65
+
66
+ ```ruby
67
+ gem "myway_config"
68
+ ```
69
+
70
+ ## Configuration Priority
71
+
72
+ Values are loaded in priority order (lowest to highest):
73
+
74
+ 1. Bundled defaults (`defaults.yml` - the `defaults:` section)
75
+ 2. Environment overrides (`defaults.yml` - e.g., `production:` section)
76
+ 3. XDG user config (`~/.config/<app>/config.yml`)
77
+ 4. Project config (`./config/<app>.yml`)
78
+ 5. Environment variables (`MYAPP_DATABASE__HOST=...`)
79
+ 6. Constructor overrides
80
+
81
+ ## Next Steps
82
+
83
+ - [Installation](getting-started/installation.md) - Get up and running
84
+ - [Quick Start](getting-started/quick-start.md) - Build your first config
85
+ - [Guides](guides/index.md) - Deep dive into features
86
+ - [API Reference](api/index.md) - Complete API documentation