rubyconfig / config

Easiest way to add multi-environment yaml settings to Rails, Sinatra, Padrino and other Ruby projects.
Other
2.1k stars 230 forks source link

Support arbitrary sources in Config.load_files and Config.load_and_set_settings #315

Closed cjlarose closed 2 years ago

cjlarose commented 2 years ago

Config.load_and_set_settings is the most convenient interface for initializing the Settings object with a bunch of configuration sources. However, one problem is that it only allows paths to YAML files. This means that if the user wants to use an explicit Config::Sources::HashSource or a Config::Sources::EnvSource such as for AWS Secrets Manager, they have to call add_source! and reload! separately.

Config.setup do |config|
  config.const_name = 'Settings'
end

Config.load_and_set_settings(
  Rails.root.join('config', 'settings', 'base.yml'),
  Rails.root.join('config', 'settings', 'default.yml')
)

secrets_source = Config::Sources::EnvSource.new(
  secrets_from_secrets_manager,
  parse_values: false
)
Settings.add_source!(secrets_source)
Settings.reload!

This is especially cumbersome if the user is using a validation contract and the settings aren't yet valid until adding the non-YAML sources. It's possible to work around this problem by setting the validation_contact after adding all sources:

Config.setup do |config|
  config.const_name = 'Settings'
end

Config.load_and_set_settings(
  Rails.root.join('config', 'settings', 'base.yml'),
  Rails.root.join('config', 'settings', 'default.yml')
)

secrets_source = Config::Sources::EnvSource.new(
  secrets_from_secrets_manager,
  parse_values: false
)
Settings.add_source!(secrets_source)

Config.validation_contract = ConfigContract.new
Settings.reload!

That's clunky. It'd be easier if the user could just specify the non-YAML sources up front.

Config.setup do |config|
  config.const_name = 'Settings'
  config.validation_contract = ConfigContract.new
end

secrets_source = Config::Sources::EnvSource.new(
  secrets_from_secrets_manager,
  parse_values: false
)

Config.load_and_set_settings(
  Rails.root.join('config', 'settings', 'base.yml'),
  Rails.root.join('config', 'settings', 'default.yml'),
  secrets_source
)

This change makes this possible. There are some breaking changes in a few edge cases, but I expect that most applications will be able to upgrade without modification.