app_configurable 0.1.0 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bbcefb59395aa424d071c1f2122d7f051e87571ff75d62eb56c80c4c3fc6ec4
4
- data.tar.gz: b095757dfcf1351ed5fabe65106dcf8a8a039a7a62744f8b811620dd0ef537f6
3
+ metadata.gz: 044562b2da9b8df939abe454b140aab3d3389a893dc2dd31f278d9e9eae8495b
4
+ data.tar.gz: 932b8ae2e26fb5449a52c815e578689ea24a88578c11df79165d42edd5a2801a
5
5
  SHA512:
6
- metadata.gz: ce77b5158704203937bc2460bf5020d4b34200598c3f85e4e5e832935f5ee29d4c784ed12ded51d159770e820ad64a74dcb9d4c5e004fa2cbc1064282901b805
7
- data.tar.gz: d9335f684c5da7ea160030d0da4d28642f73dd779059508a60a9e9b89240353a79fdaf62313936337506979c2f89b377464d08283e9f94978ab79092545ddd49
6
+ metadata.gz: 389a4ff576b8a3da9207ca41570becd67f3b5af38fb0e046c80468102ccd30a1d925f7a8817044f2ebaa88e900df26f5378972d5f92bc09bd0ac6eded9df9148
7
+ data.tar.gz: 190ec85b5ce0a351ae45d343d685a438b2b681f72746506c75ab01b5a373f5ffb493aa7d97706a0c1cabdd21878769ee4224880cd3d0afd7b1a1e99a8adacf94
data/.rubocop.yml CHANGED
@@ -26,7 +26,7 @@ Style/StringLiteralsInInterpolation:
26
26
  EnforcedStyle: double_quotes
27
27
 
28
28
  Layout/LineLength:
29
- Max: 120
29
+ Max: 180
30
30
 
31
31
  Style/ClassAndModuleChildren:
32
32
  Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_configurable (0.1.0)
4
+ app_configurable (0.1.4)
5
5
  dotenv
6
6
 
7
7
  GEM
@@ -83,7 +83,6 @@ GEM
83
83
  benchmark (0.4.0)
84
84
  bigdecimal (3.1.8)
85
85
  builder (3.3.0)
86
- byebug (11.1.3)
87
86
  concurrent-ruby (1.3.4)
88
87
  connection_pool (2.4.1)
89
88
  crass (1.0.6)
@@ -100,7 +99,7 @@ GEM
100
99
  irb (1.14.1)
101
100
  rdoc (>= 4.0.0)
102
101
  reline (>= 0.4.2)
103
- json (2.7.6)
102
+ json (2.8.2)
104
103
  language_server-protocol (3.17.0.3)
105
104
  logger (1.6.1)
106
105
  loofah (2.23.1)
@@ -113,7 +112,7 @@ GEM
113
112
  net-smtp
114
113
  marcel (1.0.4)
115
114
  mini_mime (1.1.5)
116
- minitest (5.25.1)
115
+ minitest (5.25.2)
117
116
  net-imap (0.5.1)
118
117
  date
119
118
  net-protocol
@@ -124,11 +123,19 @@ GEM
124
123
  net-smtp (0.5.0)
125
124
  net-protocol
126
125
  nio4r (2.7.4)
126
+ nokogiri (1.16.7-aarch64-linux)
127
+ racc (~> 1.4)
128
+ nokogiri (1.16.7-arm-linux)
129
+ racc (~> 1.4)
127
130
  nokogiri (1.16.7-arm64-darwin)
128
131
  racc (~> 1.4)
132
+ nokogiri (1.16.7-x86-linux)
133
+ racc (~> 1.4)
134
+ nokogiri (1.16.7-x86_64-darwin)
135
+ racc (~> 1.4)
129
136
  nokogiri (1.16.7-x86_64-linux)
130
137
  racc (~> 1.4)
131
- parallel (1.24.0)
138
+ parallel (1.26.3)
132
139
  parser (3.3.6.0)
133
140
  ast (~> 2.4.1)
134
141
  racc
@@ -173,7 +180,7 @@ GEM
173
180
  zeitwerk (~> 2.6)
174
181
  rainbow (3.1.1)
175
182
  rake (13.2.1)
176
- rdoc (6.7.0)
183
+ rdoc (6.8.1)
177
184
  psych (>= 4.0.0)
178
185
  regexp_parser (2.9.2)
179
186
  reline (0.5.11)
@@ -231,13 +238,15 @@ GEM
231
238
  zeitwerk (2.6.18)
232
239
 
233
240
  PLATFORMS
234
- arm64-darwin-23
235
- arm64-darwin-24
241
+ aarch64-linux
242
+ arm-linux
243
+ arm64-darwin
244
+ x86-linux
245
+ x86_64-darwin
236
246
  x86_64-linux
237
247
 
238
248
  DEPENDENCIES
239
249
  app_configurable!
240
- byebug
241
250
  rails (> 7.1)
242
251
  rake (~> 13.0)
243
252
  rspec (~> 3.0)
@@ -248,4 +257,4 @@ DEPENDENCIES
248
257
  rubocop-rspec_rails (~> 2.30.0)
249
258
 
250
259
  BUNDLED WITH
251
- 2.4.12
260
+ 2.5.23
data/README.md CHANGED
@@ -1,62 +1,113 @@
1
- # AppConfigurable
2
-
3
- Single source of truth for app configuration.
4
-
5
- ## Adding a new config
6
-
7
- There are 2 types of configs:
8
- - Namespaced - used to store configs which could be grouped by attributes such as external service name e.g Hubspot.
9
- - Root-level configs - generic configs for the app such as `rails_serve_static_files`.
10
-
11
- Example of namespaced config:
12
-
13
- ```ruby
14
- class AppConfig::Hubspot
15
- include AppConfigurable
16
-
17
- entry :access_token, default: 'secret'
18
- entry :base_url, default: 'https://app-eu1.hubspot.com/contacts/26265873', production: 'https://app-eu1.hubspot.com/contacts/25696692'
19
- entry :client_secret, default: 'secret'
20
- end
21
- ```
22
-
23
- Then config entries could be accessed through: `AppConfig::Hubspot.base_url`.
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
- Attributes are declared using `entry` directive.
76
+
77
+ Attributes are declared using the `entry` directive.
27
78
  Example: `entry :rails_serve_static_files`.
28
79
 
29
80
  ### Options
30
- `production/staging/development/test` - sets attributes per environment.
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.
31
86
 
32
- `default`:
33
- - sets default attribute, used in `production/staging/development` environments as a fallback.
34
- - accepts `string`/`number`/`boolean` as well as `Proc`/`Lambda` as a parameter.
35
- - in `test` environment always falls back to a dummy value `some_super_dummy_#{namespaced_attribute_name}`
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`.
36
93
 
37
- #### Priority and lifecycle:
38
- `production/staging/development`:
39
- 1) Tries to find a value in joint hash of `ENV` and `Rails.application.credentials`.
40
- 2) Gets value from specific environment attribute passed to `entry`.
41
- 3) Get's value from `default`.
42
- 4) Raises `AppConfig::Error::RequiredVarMissing` if no attribute found.
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**.
43
98
 
44
- `testing`:
45
- 1) Tries to find a value in joint hash of `ENV` and `Rails.application.credentials`.
46
- 2) Gets value from `test` environment attribute.
47
- 3) Returns `some_super_dummy_#{namespaced_attribute_name}`, ignores specified `default` attribute.
99
+ ### Setting the Environment
100
+ You can set the environment per namespace like so:
48
101
 
49
- ### Setting the environment
50
- You could set environment per namespace like so:
51
-
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
- *`.env.#{RAILS_ENV}` will be read per specific `AppConfig::SomeNiceClass` class.*
108
+ `.env.#{RAILS_ENV}` will be read per specific `AppConfig::SomeNiceClass` class.
59
109
 
60
110
  ### TODO:
61
- - Read `Rails.application.credentials`
62
- - Make dynamic switch possible, simillar to what we have with `ENV`.
111
+
112
+ - Read `Rails.application.credentials`.
113
+ - Make dynamic switch possible, similar to what we have with `ENV`.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AppConfigurable
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.4'
5
5
  end
@@ -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 ||= ::Rails.env == rails_env ? ENV.to_h : ::Dotenv.parse(".env.#{rails_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?(secrets[key.to_s])
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 = secrets.dig(*key)
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?(secrets[key.to_s])
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 or credential missing: #{self.class.name}.#{name}"
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.0
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-20 00:00:00.000000000 Z
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: byebug
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rails
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -198,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
198
184
  - !ruby/object:Gem::Version
199
185
  version: '0'
200
186
  requirements: []
201
- rubygems_version: 3.3.27
187
+ rubygems_version: 3.5.22
202
188
  signing_key:
203
189
  specification_version: 4
204
190
  summary: AppConfigurable allows you to configure your application with a simple DSL