mpope
How include layouts with render_to_iodata
I am trying to cache static web pages in ETS, and using render_to_iodata does not seem to include the layout. I was wondering the proper way to do this. Here is how I am currently using it in my controller:
def post(conn, _param) do
rendered_page = Phoenix.View.render_to_iodata(BlogWeb.LayoutView, "app.html",
%{
conn: conn,
view_module: BlogWeb.PostView,
view_template: "post.html"
})
html(conn, rendered_page)
end
What happens is that this spins forever and nothing gets loaded, and nothing is really logged to the console.
My page.html.eex:
Hello, world!
And the layout/app.html.eex (shortened) is:
<h1>Welcome!</h1>
<%= render @view_module, @view_template, assigns %>
I have a barebones view for each. I am using the default layout.
Marked As Solved
jola
Since you’re not getting any errors it’s hard to say what’s wrong. I’ve never tried to do it that way, but I can suggest an alternative solution. You can cache rendered content by using Plug.Conn.register_before_send/2. Here’s some untested code
def post(conn, _param) do
conn
|> Plug.Conn.register_before_send(cache/1)
|> render("post.html")
end
def cache(conn) do
content = :erlang.iolist_to_binary(conn.resp_body)
:ets.insert(:table, {you_pick_your_key, content})
conn
end
The reason you want to coerce the iodata to binary is that based on experience the ETS memory usage will balloon if you don’t.
This solution also means you can create a Plug responsible for checking the cache and caching responses, and add it to a pipeline. I have an example of that here https://github.com/joladev/cache_example/blob/master/lib/cache_example_web/plugs/item_cache2.ex
Note that the example is specific to my use case, you’d want to adjust it to yours 








