Conditional validation using dry-system settings


#1

I’m trying to configure a pair of related settings in my application with somewhat complicated interaction.

Application.boot(:settings, from: :system) do
  settings do
    key :option_a, Types::Strict::String.optional
    key :option_b, Types::Params.Bool.default(false)
  end
end

Either or both of OPTION_A and OPTION_B can be specified. If neither is specified, though, the application won’t work well. In a development environment I can provide a reasonable default, but it’s not a reasonable default in production. I’d sort of like to say something like

after(:start) do
  settings = target[:settings]
  if settings.option_a.nil? && !settings.option_b
    if env == :production
      # Is there a more idiomatic way to complain?
      raise 'either OPTION_A or OPTION_B must be specified'
    else
      # Can't overwrite the value in the dry-container
      target[:settings] = settings.new(option_b: true)
    end
  end
end

Any advice on the best way to do this sort of conditional, cross-option, environment-dependent option validation?


#2

It almost sound like you want to implement a high level validation rule http://dry-rb.org/gems/dry-validation/high-level-rules/

Maybe consider validating your setting with a schema at boot time?


#3

I like that idea and I could write a dry-validation filter that ran after the dry-system settings handling…but I still hit the problem that I can’t overwrite the target[:settings]. I don’t think there’s anywhere I get to hook in in between dry-system reading environment variables and environment files, and it producing the fully populated settings object and registering it in the dry-container. Is there?