Requiring configurations on specific environments only.
corroded opened this issue · 3 comments
Is your feature request related to a problem? Please describe.
This is probably a small and unpopular feature - mainly because there's an easy workaround. Still, it's a nice to have so suggesting it here. Basically we have some configurations that are only required in production
(i.e. SomeConfig.new.private_key
).
Describe the solution you'd like
I would suggest being able to set the required
config to an environment. Given you have some.yml
default: &default
host: "http://localhost"
user: "user"
development:
<<: *default
production:
<<: *default
and in some_config.rb
:
class SomeConfig < ApplicationConfig
attr_config(
:host,
:user,
:password,
)
required(
:host,
:user,
password: {only: :production}, # also consider {except: :development}
)
end
Describe alternatives you've considered
We have some couple of alternatives:
Option A: Environment specific check
This is what we have, but it feels like it goes against the idea of AnywayConfig:
class SomeConfig < ApplicationConfig
attr_config(
:host,
:user,
:password,
)
required(
:host,
:user,
)
if Rails.env.production?
required(:password)
end
end
Option B: Require it in all environments anyway
Not ideal, but also not a deal breaker:
class SomeConfig < ApplicationConfig
attr_config(
:host,
:user,
:password,
)
required(
:host,
:user,
:password,
)
end
WDYT?
I think, the feature makes sense as a part of our Rails integration; and even beyond.
Here is how we can do that:
- We can add
env:
parameter to therequired
method:
# only in production
required :api_key, env: :production
# in production and staging envs
required :api_key, env: %w[production staging]
# excluding test
required :api_key, env: { except: :test }
Thus, our signature (yeah, we now have RBS support) would be:
def self.required: (*Symbol, env: String | Symbol | Array[String | Symbol] | {except: String | Symbol | Array[String | Symbol]) -> void
- Then, we need to introduce the notion of environment. For example, we can add new setting (
settings.rb
),current_environment
. It could be set by a user or, in Rails context, could be inferred fromRails.env
.
- Then, we need to introduce the notion of environment. For example, we can add new setting (
settings.rb
),current_environment
. It could be set by a user or, in Rails context, could be inferred fromRails.env
.
Does this mean we need a special config called settings.rb
? We actually did this by making a custom loader:
# frozen_string_literal: true
# This file is a customized loader based on this file:
#
# https://github.com/palkan/anyway_config/blob/46d5f19814edbba2230dde970abbc73e6bd3ad37/lib/anyway/loaders/yaml.rb
module MyModule
module Anyway
module Rails
module Loaders
class YAML < ::Anyway::Loaders::YAML
def load_base_yml(stuff)
parsed_yml = super
return parsed_yml unless environmental?(parsed_yml)
super[custom_env] || {}
end
private
def environmental?(parsed_yml)
return true if parsed_yml.key?(custom_env)
end
def custom_env
if ::Rails.env.production?
return 'sandbox' if ENV['sandbox'].to_s == 'true'
return 'preprod' if ENV['preprod'].present?
end
::Rails.env
end
end
end
end
end
end
I meant adding a new parameter to https://github.com/palkan/anyway_config/blob/master/lib/anyway/settings.rb
(and also setting it to Rails.env
here https://github.com/palkan/anyway_config/blob/master/lib/anyway/rails/settings.rb).
Regarding your custom loader, I think it would make sense then to use the same Anyway::Settings.current_environment
in our YAML loader as well, so you won't need to build your own (and we can even re-use the base YAML loader and drop the Rails specific one).