app_configurable 0.1.1 → 0.1.4
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +97 -58
- data/lib/app_configurable/version.rb +1 -1
- data/lib/app_configurable.rb +25 -25
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 044562b2da9b8df939abe454b140aab3d3389a893dc2dd31f278d9e9eae8495b
|
4
|
+
data.tar.gz: 932b8ae2e26fb5449a52c815e578689ea24a88578c11df79165d42edd5a2801a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 389a4ff576b8a3da9207ca41570becd67f3b5af38fb0e046c80468102ccd30a1d925f7a8817044f2ebaa88e900df26f5378972d5f92bc09bd0ac6eded9df9148
|
7
|
+
data.tar.gz: 190ec85b5ce0a351ae45d343d685a438b2b681f72746506c75ab01b5a373f5ffb493aa7d97706a0c1cabdd21878769ee4224880cd3d0afd7b1a1e99a8adacf94
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
app_configurable (0.1.
|
4
|
+
app_configurable (0.1.4)
|
5
5
|
dotenv
|
6
6
|
|
7
7
|
GEM
|
@@ -112,7 +112,7 @@ GEM
|
|
112
112
|
net-smtp
|
113
113
|
marcel (1.0.4)
|
114
114
|
mini_mime (1.1.5)
|
115
|
-
minitest (5.25.
|
115
|
+
minitest (5.25.2)
|
116
116
|
net-imap (0.5.1)
|
117
117
|
date
|
118
118
|
net-protocol
|
@@ -257,4 +257,4 @@ DEPENDENCIES
|
|
257
257
|
rubocop-rspec_rails (~> 2.30.0)
|
258
258
|
|
259
259
|
BUNDLED WITH
|
260
|
-
2.5.
|
260
|
+
2.5.23
|
data/README.md
CHANGED
@@ -1,74 +1,113 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
Single source of truth for app configuration
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
# App Configurable
|
2
|
+
|
3
|
+
## Single source of truth for app configuration
|
4
|
+
|
5
|
+
App Configurable is a simple Ruby gem that provides a centralized and consistent way to manage application configurations. It allows you to define configurations in a single place and access them throughout your application, ensuring that your app's settings are always up-to-date and consistent across different environments.
|
6
|
+
|
7
|
+
### Features
|
8
|
+
- Centralized configuration management
|
9
|
+
- Environment-specific settings
|
10
|
+
- Fail on demand or on app startup
|
11
|
+
- Support for namespaced and root-level configurations
|
12
|
+
- Easy integration with Rails applications
|
13
|
+
|
14
|
+
### Installation
|
15
|
+
1. Add the gem to your Gemfile:
|
16
|
+
```ruby
|
17
|
+
gem 'app_configurable'
|
18
|
+
```
|
19
|
+
2. Define your configurations in `config/app_config.rb`:
|
20
|
+
```ruby
|
21
|
+
class AppConfig
|
22
|
+
include AppConfigurable
|
23
|
+
|
24
|
+
entry :secret_key, default: 'your_secret_key'
|
25
|
+
entry :base_url, default: 'http://my-site.local', production: 'http:// my-site.io', staging: 'http://staging.my-site.io'
|
26
|
+
end
|
27
|
+
```
|
28
|
+
3. Load the configurations:
|
29
|
+
|
30
|
+
Define an initializer `config/initializers/_app_config.rb`:
|
31
|
+
```ruby
|
32
|
+
AppConfigurable.load(%w[./config/app_config.rb])
|
33
|
+
```
|
34
|
+
OR
|
35
|
+
```ruby
|
36
|
+
AppConfigurable.load(%w[./config/app_config.rb], raise_on_missing: true) # Fails on startup, reporting missing configs.
|
37
|
+
```
|
38
|
+
*Alternatively, you could define your configs under the autoloading path if failing on demand is acceptable.*
|
39
|
+
|
40
|
+
4. Access your configurations:
|
41
|
+
```ruby
|
42
|
+
AppConfig.secret_key
|
43
|
+
```
|
44
|
+
|
45
|
+
### Adding a config
|
46
|
+
There are two types of configurations:
|
47
|
+
- **Namespaced**: Used to store configurations grouped by attributes such as external service names (e.g., Hubspot).
|
48
|
+
- **Root-level configs**: Generic configurations for the app, such as `rails_serve_static_files`.
|
49
|
+
|
50
|
+
### Example
|
51
|
+
`./config/app_config.rb`:
|
52
|
+
```ruby
|
53
|
+
class AppConfig
|
54
|
+
include AppConfigurable
|
55
|
+
|
56
|
+
entry :secret_key_base, default: 'secret_key_base'
|
57
|
+
entry :base_url, default: 'http://my-site.local', production: 'http:// my-site.io', staging: 'http://staging.my-site.io'
|
58
|
+
entry :client_secret, default: 'client_secret_token'
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
`./config/app_config/hubspot.rb`:
|
63
|
+
```ruby
|
64
|
+
class AppConfig::Hubspot
|
65
|
+
include AppConfigurable
|
66
|
+
|
67
|
+
entry :access_token, default: 'secret_access_token'
|
68
|
+
entry :base_url, default: 'https://hubspot.com/1234', production: 'https:// hubspot.com/4321'
|
69
|
+
entry :client_secret, default: 'client_secret_token'
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
Declared configs can be accessed through: `AppConfig.secret_key_base` and `AppConfig::Hubspot.base_url`.
|
24
74
|
|
25
75
|
## Attributes
|
26
|
-
|
76
|
+
|
77
|
+
Attributes are declared using the `entry` directive.
|
27
78
|
Example: `entry :rails_serve_static_files`.
|
28
79
|
|
29
80
|
### Options
|
30
|
-
|
31
|
-
|
32
|
-
`
|
33
|
-
-
|
34
|
-
-
|
35
|
-
- in `test` environment always falls back to a dummy value `some_super_dummy_#{namespaced_attribute_name}`
|
81
|
+
- **production/staging/development/test**: Sets attributes per environment.
|
82
|
+
- **default**:
|
83
|
+
- Sets the default attribute, used in `production/staging/development` environments as a fallback.
|
84
|
+
- Accepts `string`/`number`/`boolean` as well as `Proc`/`Lambda` as a parameter.
|
85
|
+
- In the `test` environment, always falls back to a dummy value `some_super_dummy_#{namespaced_attribute_name}` unless specified explicitly.
|
36
86
|
|
37
|
-
#### Priority
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
87
|
+
#### Priority
|
88
|
+
- **production/staging/development**:
|
89
|
+
1. Find value in `ENV`.
|
90
|
+
2. Find value in specific environment attribute passed to `entry`.
|
91
|
+
3. Find value from `default`.
|
92
|
+
4. Fail with `AppConfig::Error::RequiredVarMissing`.
|
43
93
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
94
|
+
- **testing**:
|
95
|
+
1. Find value in `ENV`.
|
96
|
+
2. Find value in `test` attribute of config `entry`.
|
97
|
+
3. Return `some_super_dummy_#{namespaced_attribute_name}`, **ignoring the specified `default` attribute**.
|
48
98
|
|
49
|
-
### Setting the
|
50
|
-
You
|
99
|
+
### Setting the Environment
|
100
|
+
You can set the environment per namespace like so:
|
51
101
|
|
52
|
-
Given namespace `AppConfig::MyNiceConfigClass` and `.env.staging
|
102
|
+
Given namespace `AppConfig::MyNiceConfigClass` and `.env.staging`:
|
53
103
|
|
54
104
|
```bash
|
55
105
|
APPCONFIG_MYNICEMODULE_ENV=staging rspec
|
56
106
|
```
|
57
107
|
|
58
|
-
|
59
|
-
|
60
|
-
### Fail on startup:
|
61
|
-
Create a new initializer in `config/initializers/_app_config.rb`
|
62
|
-
|
63
|
-
```
|
64
|
-
# Require your config files
|
65
|
-
require './config/app_config' # Root-level configs.
|
66
|
-
FileList['./config/app_config/*.rb'].each { |file| require file } # Secondary-level/namespaced configs.
|
67
|
-
|
68
|
-
missing = AppConfigurable.missing_required_vars
|
69
|
-
missing.present? and raise "Missing required ENV variables/encrypted credentials: #{missing.inspect}"
|
70
|
-
```
|
108
|
+
`.env.#{RAILS_ENV}` will be read per specific `AppConfig::SomeNiceClass` class.
|
71
109
|
|
72
110
|
### TODO:
|
73
|
-
|
74
|
-
|
111
|
+
|
112
|
+
- Read `Rails.application.credentials`.
|
113
|
+
- Make dynamic switch possible, similar to what we have with `ENV`.
|
data/lib/app_configurable.rb
CHANGED
@@ -18,10 +18,26 @@ module AppConfigurable
|
|
18
18
|
owner.include InstanceMethods
|
19
19
|
end
|
20
20
|
|
21
|
+
# Returns the list of available configuration attributes,
|
22
|
+
# which are defined with the `entry` method.
|
23
|
+
# @return [Array]
|
21
24
|
def self.available_config_attributes
|
22
25
|
@@available_config_attributes
|
23
26
|
end
|
24
27
|
|
28
|
+
# @param paths [Array] List of paths to load.
|
29
|
+
# @param raise_on_missing [Boolean] Raise an error if required variables are missing, default is `false`.
|
30
|
+
# @return [void]
|
31
|
+
def self.load_configs(paths = [], raise_on_missing: false)
|
32
|
+
paths.each do |path|
|
33
|
+
absolute_path = Dir.pwd + "/#{path}"
|
34
|
+
|
35
|
+
File.directory?(absolute_path) ? Dir["#{absolute_path}/**/*.rb"].each { |f| require f } : require(absolute_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
raise_on_missing && missing_required_vars.any? && raise(Error::RequiredVarMissing, missing_required_vars.join(', '))
|
39
|
+
end
|
40
|
+
|
25
41
|
# Report missing required `ENV` variables.
|
26
42
|
# @return [Array]
|
27
43
|
def self.missing_required_vars
|
@@ -118,16 +134,14 @@ module AppConfigurable
|
|
118
134
|
attrs.each { |k, v| public_send(:"#{k}=", v) }
|
119
135
|
end
|
120
136
|
|
121
|
-
# A *copy* of the credentials for value-reading purposes.
|
122
|
-
# @return [Hash]
|
123
|
-
def credentials
|
124
|
-
@credentials ||= ::Rails.application&.credentials.to_h
|
125
|
-
end
|
126
|
-
|
127
137
|
# A *copy* of the environment for value-reading purposes.
|
128
138
|
# @return [Hash]
|
129
139
|
def env
|
130
|
-
@env ||=
|
140
|
+
@env ||=
|
141
|
+
begin
|
142
|
+
result = ::Rails.env == rails_env ? ENV.to_h : ::Dotenv.parse(".env.#{rails_env}")
|
143
|
+
result.deep_transform_keys!(&:downcase).with_indifferent_access
|
144
|
+
end
|
131
145
|
end
|
132
146
|
|
133
147
|
# @!attribute rails_env
|
@@ -171,13 +185,13 @@ module AppConfigurable
|
|
171
185
|
|
172
186
|
# @see #env_truthy?
|
173
187
|
def env_falsey?(key)
|
174
|
-
self.class.env_value_falsey?(
|
188
|
+
self.class.env_value_falsey?(env[key.to_s])
|
175
189
|
end
|
176
190
|
|
177
191
|
# @param key [String/Symbol]
|
178
192
|
# @return [String/Boolean] The value of the environment variable, converts `bolean`'ish values into boolean.
|
179
193
|
def env_value(key)
|
180
|
-
v =
|
194
|
+
v = env.dig(*key)
|
181
195
|
v = env_truthy?(key) if env_boolean?(key)
|
182
196
|
v
|
183
197
|
end
|
@@ -190,7 +204,7 @@ module AppConfigurable
|
|
190
204
|
# @param key [String]
|
191
205
|
# @return [Boolean]
|
192
206
|
def env_truthy?(key)
|
193
|
-
self.class.env_value_truthy?(
|
207
|
+
self.class.env_value_truthy?(env[key.to_s])
|
194
208
|
end
|
195
209
|
|
196
210
|
# @param name [Symbol/String]
|
@@ -209,7 +223,7 @@ module AppConfigurable
|
|
209
223
|
result = default_value.call(dummy_value) if result.nil?
|
210
224
|
if result.nil?
|
211
225
|
raise Error::RequiredVarMissing,
|
212
|
-
"Required ENV variable
|
226
|
+
"Required ENV variable is missing: #{self.class.name}.#{name}"
|
213
227
|
end
|
214
228
|
|
215
229
|
result
|
@@ -232,14 +246,6 @@ module AppConfigurable
|
|
232
246
|
send(:env)
|
233
247
|
end
|
234
248
|
|
235
|
-
# TODO: Implement this. Currently it's not re-reading secrets after enviromnemt change.
|
236
|
-
# Recalculates the `credentials` hash.
|
237
|
-
# @return [void]
|
238
|
-
def recalculate_credentials
|
239
|
-
remove_instance_variable(:@credentials) if instance_variable_defined?(:@credentials)
|
240
|
-
send(:credentials)
|
241
|
-
end
|
242
|
-
|
243
249
|
# Recalculates the values of all the attributes.
|
244
250
|
# @return [void]
|
245
251
|
def recalculate_values
|
@@ -248,11 +254,5 @@ module AppConfigurable
|
|
248
254
|
send(a)
|
249
255
|
end
|
250
256
|
end
|
251
|
-
|
252
|
-
# Joint hash of `ENV` and `Rails.application.credentials`
|
253
|
-
# @return [HashWithIndifferentAccess]
|
254
|
-
def secrets
|
255
|
-
{ **env }.deep_transform_keys!(&:downcase).with_indifferent_access
|
256
|
-
end
|
257
257
|
end
|
258
258
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: app_configurable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmytro Pasichnyk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv
|
@@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
184
|
- !ruby/object:Gem::Version
|
185
185
|
version: '0'
|
186
186
|
requirements: []
|
187
|
-
rubygems_version: 3.
|
187
|
+
rubygems_version: 3.5.22
|
188
188
|
signing_key:
|
189
189
|
specification_version: 4
|
190
190
|
summary: AppConfigurable allows you to configure your application with a simple DSL
|