Accessing routes in the domain layer without including MyAppWeb in MyApp context

Hi all,

I am sending lifecycle emails from my the MyApp context. I’m using Bamboo.Template like so:

defmodule MyApp.Notifications do
  use Bamboo.Template, view: MyApp.Notifications.Views.EmailView

  def welcome(many-params) do
    base_email()
      |> to(email)
      |> subject("Welcome")
      |> assign(:user, user)
      |> put_text_layout({MyApp.Notifications.Views.EmailView, "welcome.text"})
      |> put_text_layout({MyApp.Notifications.Views.EmailView, "welcome.html"})
      |> render(:welcome)
      |> Mailer.deliver_later()
  end
end

The benefit of Bamboo.Template is that I don’t have to include Phoenix web layer concerns or MyAppWeb in the context.

In the welcome.html.eex email I would like to include a url like a verify_email_url or a referral_url.

How do I get the needed url paths, specified in the Router (which is in Web), into my context layer?

Thank you

I think you should use the path helpers. I know that it feels like it’s breaking the boundary, but the web concern truly is a dependency for this email, no?

3 Likes

Fwiw, this is what I have done too. I just go ahead and use

MyAppWeb.Router.Helpers.some_url(...)

right in MyApp.Email.

2 Likes

Thank you for your reply.

but the web concern truly is a dependency for this email, no?

I feel like it’s not that there’s a web concern that’s a dependency, but that there is a dependency IN the web layer that I’d like access to. Perhaps I’m over thinking this but it seems like routes are just strings. They only get meaning and behavior when looked at from a web browser’s perspective. Otherwise, they’re just strings in a certain shape. But yeah, perhaps over thinking.

Looks like I’ll include MyApp web and just finish the feature :sweat_smile:

1 Like

You could always send the url as a parameter to the email logic.

1 Like

hi, may this help towards maintainable elixir the core and the interface section Activation mail using UrlProvider

2 Likes

Another option is to place all the email specific functionality (Mailer module, Email module, views, templates) into a separate directory in lib next to, but dependent upon, MyApp and MyAppWeb under something like MyAppMail.

1 Like

Problem is that if he wants to actually make sure everytime a domain logic is called the email is sent. The best way to do that is to write the email on domain logic too, if he creates a new folder and call that folder code from MyApp, which then calls code from MyAppWeb, then indirectly MyApp still depends from MyAppWeb. And if he calls the email logic from MyAppWeb, he has to remember to do that manually everytime the specific domain logic is called.

1 Like

Yeah, separating the email modules out on their own probably helped me somewhat justify in my mind that making the dependencies obvious and self-contained ameliorated the smell of the implied dependency. But it doesn’t. :slight_smile: I experimented with passing the URLs in various cases (scheduled messages, controller, etc.), but wasn’t too happy with it. The UrlProvider post mentioned in an earlier message above seems like a clean way to do it though. Thanks for the push to get back to eliminating this dependency.

1 Like