Global HR — 6 min
Engineering — 2 min
At Remote.com we’re heavy users of Phoenix Framework. As we make good progress to ship the new Remote.com there are a few tips and tricks we’re happy to share.
We’re using coherence as the backbone for our auth system. It’s quite easy and fast to setup.
Soon after you finish all requirements and setup procedures it’ll be time to get going and actually implement some auth flows.
If you already implemented your fair share of web systems, I’m sure the term and/or variable current_user is one you know all too well.
If that isn’t the case, well, in short, it’s typically a variable populated with a data structure or record identifying the user that originated the respective request.
A very common way to access this variable without having to fetch it explicitely from conn in every action of our controller is to override the action plug.
As a first attempt to simplify that, you can do the following:
1defmodule MyApp.UserController do2 use MyApp.Web, :controller34 def action(%Plug.Conn{assigns: %{current_user: current_user}} = conn, _opts) do5 apply(__MODULE__, action_name(conn), [conn, conn.params, current_user])6 end78 def show(conn, _params, current_user) do9 render(conn, "show.html", logged_in: current_user)10 end
As you can see we now have a function called action which will override Phoenix’s controller default action/2 plug allowing us to inject custom arguments. More about this here.
Although this is a lot better, it’s still not very DRY as we’d need to replicate this function all over every single controller in which we need to access current_user.
We improved this by creating the following module in controllers/helpers/current_user.ex:
1defmodule MyApp.CurrentUser do2 defmacro __using__(_) do3 quote do4 def action(%Plug.Conn{assigns: %{current_user: current_user}} = conn, _opts) do5 apply(__MODULE__, action_name(conn), [conn, conn.params, current_user])6 end7 end8 end9end
This time we applied Elixir’s defmacro to allow us to seamlessly inject the function into our controllers. With this we can access current_user very easily and remove unnecessary, repeated code, like this:
1defmodule MyApp.UserController do2 use MyApp.Web, :controller3 use MyApp.CurrentUser45 def show(conn, _params, current_user) do6 render(conn, "show.html", logged_in: current_user)7 end
How cool is that? With a simple, single line of code we can inject current_user into every action.
Do you have any suggestions on how to improve this? We’d love to hear from you.
Subscribe to receive the latest
Remote blog posts and updates in your inbox.
Global HR — 6 min
Global HR — 8 min
Global Employment & Expansion — 11 min
Global Payroll — 11 min