Hanami Mailer in Hanami 2 with slices

Hey :wave:,

I’m using Hanami Mailer in a Hanami 2 app with multiple slices. I want to configure the Mailer once for the whole app, but each slice should be able to have its own mailers.

This is the provider for the whole app


Hanami.app.register_provider(:mailers, namespace: true) do
  prepare do
    require "hanami/mailer"

    @mail_config = Hanami::Mailer::Configuration.new do |config|
      # Set the root path where to search for templates
      # Argument: String, Pathname, #to_pathname, defaults to the current directory
      #
      config.root = "app/mailers/templates"

      # Set the default charset for emails
      # Argument: String, defaults to "UTF-8"
      #
      config.default_charset = "UTF-8"

      # Set the delivery method
      # Argument: Symbol
      # Argument: Hash, optional configurations

      settings = target["settings"]
      config.delivery_method = :smtp, { address: settings.smtp_server, port: settings.smtp_port }
    end
  end

  start do
    register "mailer_config", Hanami::Mailer.finalize(@mail_config)
  end
end

And in the slice-providers I want to register the slice mailers using the mailer_config. That all sounds great, and would work if there weren’t the root setting in the Hanami::Mailer::Configuration.

With this root config it is not possible to manage the templates in the slices. Does anyone here have a workaround, or know whether a change is planned here?

Thanks!

Split the configuration into a separate key.

Admin::Slice.register_provider(:mailers, namespace: true) do
  prepare do
    target["mailer.config"].start

    @mail_config = target["mailer.config"].with do |config|
      config.root = target.root / "mailers" / "templates"
    end
  end
end
1 Like

@alassek Thanks.
The issue with your approach is, that a FrozenError is thrown, when we finalize the config Hanami::Mailer.finalize(@mailer_config).

Admin::Slice.register_provider(:mailers, namespace: true) do
  prepare do
    app_mailer_config = Hanami.app["mailer.config"]

    @mailer_config = app_mailer_config.with do |config|
      config.root = "slices/admin/mailers/templates"
    end
  end

  start do
    register "welcome_mailer", Admin::Mailers::WelcomeMailer.new(configuration: Hanami::Mailer.finalize(@mailer_config))
  end
end

This happens because the #with-method freezes the hash.

Thanks

Hmm, yeah freezing the config in with is surprising. Looks like you could duplicate instead

@mailer_config = Hanami.app["mailer.config"].duplicate
@mailer_config.root = "slices/admin/mailers/templates"

You would need to do this in app as well so the config doesn’t get frozen.

This is a little fiddly, so maybe writing your own config builder would be more straightforward. Or add a monkeypatch/refinement that adds initialize_copy.