One gotcha with new Phoenix 1.7 for me has been the dynamic parts of the layouts, i.e. meta tags for descriptions, preloading, canonical and whatnot. Open graph tags. Also optional JS scripts for things like AdSense or some captcha. And many more.
And it seems like the best way to approach this is through assigns
. But building all those assigns in a controller seems strange to me, especially when it's about meta tags or JS. So my approach includes using presenter
modules, something like that (pseudo code):
def show(conn, _) do
conn
|> assign(:adsense_script, AdsensePresenter.script_tag())
|> assign(:open_graph, OpenGraphPresenter.tags())
|> render(:show)
end
And while it's okay, it still feels like it doesn't belong in the controller, so I wonder if anyone has come up with more elegant solution to this?
UPDATE #1
Another idea that I have is to have a layout function that checks how the layout was rendered and calls a function from that module:
# layouts.ex
defp page_description(assings) do
module_function(assigns, :page_description)
end
defp module_function(assigns, name) do
module = assigns[:live_module] || view_module(assigns[:conn])
if function_exported?(module, name, 1) do
apply(module, name, [assigns])
end
end
And then in HTML or Live modules add a function:
# main_page_html.ex or main_page_live.ex
def page_description(_) do
"My main page description here"
end