Module: Mailkube::Rails::Config

Defined in:
lib/mailkube/rails/config.rb,
sig/mailkube/rails.rbs

Overview

The one place this gem turns Rails settings into SDK constructor arguments.

Everything that reaches the SDK goes through Config.build_client: the delivery method, the webhook endpoint, and anything added later. Two call sites building their own client is how one of them ends up on a different base URL, or without the User-Agent suffix, and the difference shows up as a support question rather than as a failing test.

Two homes, and no precedence rules

Settings live in the two places Rails already puts these kinds of settings, and they do not overlap, so there is nothing to resolve between them:

  • config.action_mailer.mailkube_settings — the delivery credentials. This hash is what add_delivery_method creates, and ActionMailer hands it to the delivery method for every message, so it is the idiomatic home and needs no invention.
  • config.mailkube — the webhook secret and freshness window, on the ActiveSupport::OrderedOptions the Railtie installs. These are not delivery settings and putting them under action_mailer would misfile them.

Constant Summary collapse

CLIENT_KEYS =

SDK constructor keywords, mapped to the settings key that answers each.

One list, so a setting cannot be readable in the delivery method and quietly ignored in a startup check. Adding an SDK keyword is a row here and nothing else.

Returns:

  • (Hash[Symbol, Symbol])
{ api_key: :api_key, base_url: :base_url, timeout: :timeout }.freeze

Class Method Summary collapse

Class Method Details

.build_client(settings) ⇒ Mailkube::Client

Build an SDK client from a delivery-method settings hash.

Parameters:

  • settings (Hash{Symbol => Object}, nil)

    the mailkube_settings hash.

  • (Hash[Symbol, untyped], nil)

Returns:

  • (Mailkube::Client)

    the client, carrying this gem's User-Agent suffix.

Raises:

  • (Mailkube::ConfigurationError)

    when no API key is available anywhere.



35
36
37
38
39
40
# File 'lib/mailkube/rails/config.rb', line 35

def self.build_client(settings)
  # Splatted as keywords: a setting this gem did not resolve is simply not passed, which is
  # what leaves the SDK's own default and its environment fallback in charge. Passing an
  # explicit nil would suppress that fallback while looking like configuration.
  Mailkube::Client.new(**client_kwargs(settings), user_agent_suffix: user_agent_suffix)
end

.client_kwargs(settings) ⇒ Hash{Symbol => Object}

Resolve the SDK keywords that are actually set, dropping the rest.

Parameters:

  • settings (Hash{Symbol => Object}, nil)

    the mailkube_settings hash.

  • (Hash[Symbol, untyped], nil)

Returns:

  • (Hash{Symbol => Object})

    the keywords to pass to the SDK.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/mailkube/rails/config.rb', line 46

def self.client_kwargs(settings)
  given = settings || {}
  kwargs = {} #: Hash[Symbol, untyped]
  CLIENT_KEYS.each do |keyword, key|
    value = given[key]
    # An empty string is treated as unset. It is what an unset `ENV["..."]` interpolated
    # into an initializer produces, and passing it through would defeat the SDK's fallback
    # while looking like a configured value.
    next if value.nil? || value == ""

    kwargs[keyword] = value
  end
  kwargs
end

.options(app_config) ⇒ ActiveSupport::OrderedOptions

The gem's own options block, tolerating an application that never set one.

ActiveSupport::OrderedOptions answers nil for any unset key, so this returns an empty one rather than nil and every reader above stays a single expression.

Parameters:

  • app_config (Object)

    an object responding to mailkube.

  • (Object)

Returns:

  • (ActiveSupport::OrderedOptions)

    the options block.



96
97
98
# File 'lib/mailkube/rails/config.rb', line 96

def self.options(app_config)
  app_config.mailkube || ActiveSupport::OrderedOptions.new
end

.user_agent_suffixString

This gem's own name/version token for the SDK's User-Agent.

Read from VERSION rather than written here. A literal would be a second source of truth that the release process does not update, so it would go stale on the first release and stay wrong for every one after it. The SDK's own token stays leading, so the result is mailkube/1.1.0 mailkube-rails/0.1.0.

Returns:

  • (String)

    the suffix token.



69
# File 'lib/mailkube/rails/config.rb', line 69

def self.user_agent_suffix = "mailkube-rails/#{VERSION}"

.webhook_secret(app_config) ⇒ String?

The webhook signing secret, or nil when none is configured.

Parameters:

  • app_config (Object)

    an object responding to mailkube, normally ::Rails.application.config.

  • (Object)

Returns:

  • (String, nil)

    the secret, or nil.



75
76
77
78
# File 'lib/mailkube/rails/config.rb', line 75

def self.webhook_secret(app_config)
  value = options(app_config).webhook_secret
  value.is_a?(String) && !value.empty? ? value : nil
end

.webhook_tolerance(app_config) ⇒ Integer?

The signature freshness tolerance, or nil to accept the SDK's documented default.

Parameters:

  • app_config (Object)

    an object responding to mailkube.

  • (Object)

Returns:

  • (Integer, nil)

    the window in seconds, or nil.



84
85
86
87
# File 'lib/mailkube/rails/config.rb', line 84

def self.webhook_tolerance(app_config)
  value = options(app_config).webhook_tolerance
  value.nil? ? nil : Integer(value)
end