AlchemistCamp
I have several apps with something like the following in the app.html.eex or app.html.heex:
<%= render_existing(view_module(@conn), "_meta." <> view_template(@conn), assigns)
|| render AppWeb.LayoutView, "_meta.html", assigns %>
This setup renders the metadata for a given view “foo.html” by looking for “_meta.foo.html” and rendering it if it exists. I use the meta templates for holding SEO-related meta, OG meta, and various other tags that go into the tag of a document.
If meta doesn’t exist, then the logic above renders a default template called layout/_meta.html. as the default source.
After upgrading Phoenix, I’m now seeing a compilation warning telling me to use function_exported?/3 instead of render_existing/3.
warning: Phoenix.View.render_existing/3 is deprecated. Use function_exported?/3 instead
lib/app_web/templates/layout/app.html.eex:2: AppWeb.LayoutView."app.html"/1
What would be a good way of following this advice (without breaking the behavior of 100+ _meta templates)? There’s a considerable gap in the interface of the suggested replacement function.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex











First 10 of 11 Posts
msimonborg
Perhaps one approach would be to define a global view helper
render_meta/2and call it in your templates with
render_meta(@conn, assigns)Also I’m not 100% sure, but I think you can remove the module name
view_module(@conn)from yourrendercall when you’re referencing the view that you’re calling from.EDIT: There are some examples on using
function_exported?/3in the docs if you want to follow the compiler warning’s suggestion, but seems like it might require you to rewrite your meta templates into functionsKurisu
Of course it will do it. I’m very tempted to implement something similar for some static templates I have for several locales:
render_existing_locale/2. Each template is suffixed with a locale.Exactly that is the conclusion I also came to after trying that.
By the way could someone, please, elaborate a bit on the story behind this deprecation ?
Knowing it would prevent some people from reproducing by other means that very mistake that the Phoenix team want to discourage.
AlchemistCamp
I looked at the docs before creating this thread. It’s because the examples provided weren’t applicable to my use case that I asked here in the first place.
I’ve found that
_meta.foo.htmlfiles for simpler cases and defining arender("_meta.foo.html", assigns)functions in the view for more complex cases a very useful pattern.Kurisu
When I was talking about certain people I meant of course less experienced developers like myself. I realize now that you might misinterpret it. I apologize if you felt targeted.
AlchemistCamp
Oh, not at all! Your comment was fine.
I was just clarifying that I had already looked through the suggestions and hadn’t seen a way to apply them to this use case.
I also wonder the exact same thing you asked. Was there a usage the team was trying to prevent by deprecating the function? Or was it maybe for some more general optimization in Phoenix?
I’m curious.
LostKobrakai
The idea is moving to function components over templates. Function components are a lot more flexible than templates and given they’re based on (differently named) functions there’s less phoenix magic needed – magic the phoenix teams seems to like to get away from. But not everybody will jump on board of restructing their projects immediately, therefore I feel the deprecation was a bit premature.
You’d replace your code with something like this:
From those meta functions you can also call your existing templates using:
AlchemistCamp
Hmm… this will mean making a new function for every single template, which is enough that I’d rather not upgrade some of my apps.
It’s a really useful idea, though. It feels like it’s close. I’ll mess around with this and see if I can come up with something that fixes the issue without writing a hundred new functions. Thank you so much for the help!
I feel a lot more motivated to tackle this upgrade again. I’ll share results when I come up with something.
AlchemistCamp
The trickiest part is how to programatically determine if that template exists and is safe to call. E.g., in many cases,
_meta.show.html.eexexists, but_meta.edit.html.eexdoes not (since SEO isn’t a concern for that action).AlchemistCamp
I gave it my best shot this morning during a livestream before work and unfortunately, just couldn’t get a working solution.
Without
render_existing/3, we can no longer determine whether a template exists. Depending on deployment strategies, the filesystem is sometimes no longer available.Unfortunately,
function_exported?/3doesn’t fill the gap sincerender/3will always be exported.This means the only options would be
Awlexus
I’ve also not been able to find an adequate solution without using one of the options you listed, and went with the route I look for layout files at compile time.
This is how I render additional actions (buttons) in the navbar, if the view defines a layout for the current action. I hope it’s easy enough to adjust for your needs and save you some time.
action_view.ex
You can
use MyAppWeb.ActionViewon views that provide additional actions or inview/0inmy_app_web.exand call it in your HTML files like below.