Bleeding boundaries (contexts vs web)

I have a Accounts context. One of its jobs is to invite new users.

MyApp.Accounts.invite(%{...})

I invoke it from my controller like so.

def create(conn, %{"user" => user_params}) do
    case Accounts.invite_user(user_params) do
      {:ok, user} ->
        conn
       ...
      {:error, %Ecto.Changeset{} = changeset} ->
       ...
    end
  end

I would like for the email to be sent as a part of the logic from invite_user/1 and this is where things get a little funky.

Currently I’m using Bamboo and there seems to be a lot of nice helpers for rending views ect.
Such as use Bamboo.Phoenix, view: MyApp.EmailView But right there I start to think this logic belongs in the web side of things not in my context side. To make things worse I’m finding there is a need to pass conn from the controller to invite_user because I need to give it to the templates for use with route helpers.

My question is not so directly related to the context above, but rather where do you draw the line from bleeding things from your web side into the context side? IE: I’ve been told that I should not send the conn to my context since its really the concern of the controller, does that mean I should extract the logic for emailing in to my controller / web side?

IDK, just feeling like designing right now is really hard.
I guess my point is that I’m finding myself calling logic back and forth between calling web logic from in my contexts and that feels like a smell. Thoughts?

Maybe this is interesting to you: Mailers in Phoenix 1.3 - in /web directory or not?

For your route helpers you don’t really need the conn, as you can use your Endpoint module just as well. It’s true that you’re then depending with your mailer on the existance of your web interface, but really that’s how it goes if you want to guide the user to your web interface with emails. If you really want to you could have a low level mailer context and a high level web-mailer context, which then depends on phoenix and your low level mailer.

Edit:

To be a bit more explicit. Sending emails doesn’t have anything to do with the web request/response cycle besides possibly being triggered from there. On the other hand depending on something like Phoenix.View/MyApp.Endpoint does not mean you’re depending on a web request (conn), which is the bad thing to do, so you could still send an email from iex without problems.

2 Likes

Thank you that gave enough to work with.