elixirplug

Is there a way to get the modified data from within a EEx template


I'm using EEx template engine to render HTML pages (no Phoenix here). I'm passing the connection (Plug.Conn) conn to the template along with extracted parameter list (params) and the session map (session) with : body = EEx.eval_file(path, conn: conn, params: conn.params, session: session). params and session are provided just for convenience as they also are in the connection.

If the page modifies the session (configured with cookies), say with something like <% Plug.Conn.put_session(conn, "reply", 42) %>), this modifies the connection but this also remains local to the page and is not propagated.

Is there a way to retrieve this modified version of the connection from the EEx engine ?

NB: I'm talking about the connection (Plug.Conn), but it could be any variable that is modified or created by the template engine, just a similar way Code.eval_string("a=1\n b=2\n c=a+b") does : {3, [a: 1, b: 2, c: 3]}.


Solution

  • EEx.eval_file and EEx.eval_string both return a String type, they do not return the updated bindings (as, like you say, Code.eval_string does).

    I think the reasoning behind this is that you want a render function to have no side-effects (like database calls or session modification).

    You don't want business-logic in your templates, you want to put that in your controller or data layer (with the advantage that you can test it in isolation).

    Maybe offtopic, but if you're coming from a PHP background (where you can put all your code in one file that looks like an HTML template) this might be the source of the confusion.

    Update

    This could work though:

    quoted = EEx.compile_string("<%= c = a + b %>")
    {result, bindings} = Code.eval_quoted(quoted, [a: 1, b: 2])
    
    Keyword.fetch(bindings, :c) # {:ok, 3}