thoughtbot/bamboo_phoenix

Text template required even when using only `put_html_layout`

sepowitz opened this issue · 2 comments

Hey there,

Firstly, just wanted to thank you for creating/maintaining the Bamboo family of libs, they really make email rendering easy!

I am using bamboo-phoenix to render email templates using Phoenix views.

I setup a basic example:

my_app_web/emails/invite.ex

defmodule MyAppWeb.InviteEmail do
  use Bamboo.Phoenix, view: MyAppWeb.EmailView

  def invite do
    new_email()
    |> from("noreply@myapp.com")
    |> put_html_layout({MyAppWeb.LayoutView, "email.html"})
    |> to("hello@myapp.com")
    |> subject("You've been invited")
    |> render(:invite)
  end
end
my_app_web/views/email_view.ex

defmodule MyAppWeb.EmailView do
  use MyAppWeb, :view
end
my_app_web/templates/email.html.eex

<html>
  <body>
    <%= render @view_module, @view_template, assigns %>
  </body>
</html>
my_app_web/templates/email/invite.html.eex

<h1>You've been invited!</h1>

I have a basic test, just to ensure the email is successfully created, however, when I run the test I get the following error:

     ** (Phoenix.Template.UndefinedError) Could not render "invite.text" for MyAppWeb.EmailView, please define a matching clause for render/2 or define a template at "lib/my_app_web/templates/email/*". The following templates were compiled:

     * invite.html

     Assigns:

     %{view_module: MyAppWeb.EmailView, view_template: "invite.text"}

     Assigned keys: [:view_module, :view_template]
     
          stacktrace:
       (phoenix 1.5.7) lib/phoenix/template.ex:337: Phoenix.Template.raise_template_not_found/3
       (phoenix 1.5.7) lib/phoenix/view.ex:472: Phoenix.View.render_to_iodata/3
       (phoenix 1.5.7) lib/phoenix/view.ex:479: Phoenix.View.render_to_string/3
       (bamboo_phoenix 1.0.0) lib/bamboo_phoenix.ex:283: Bamboo.Phoenix.render_html_and_text_emails/1
       test/my_app_web/emails/invite_test.exs:5: (test)

If I add an invite.text.eex template, then the test runs just fine, however, I'm only calling put_html_layout({MyAppWeb.LayoutView, "email.html"}) from my email module, so not sure why it requires me to also have a text template.

Any help would be greatly appreciated!

Hi @sepowitz thanks for opening the issue.

When passing an atom, Bamboo assumes you want to render both html and text templates. If you only want to render the html template, you should change the render call to pass a string:

my_app_web/emails/invite.ex

defmodule MyAppWeb.InviteEmail do
  use Bamboo.Phoenix, view: MyAppWeb.EmailView

  def invite do
    new_email()
    |> from("noreply@myapp.com")
    |> put_html_layout({MyAppWeb.LayoutView, "email.html"})
    |> to("hello@myapp.com")
    |> subject("You've been invited")
-    |> render(:invite)
+    |> render("invite.html")
  end
end

That's highlighted in the render/3's docs, but if you have suggestions for improving those docs, contributions are always welcome.

Let me know if that fixes your issue.

@germsvel Really appreciate it! Fixes my issue.