Plug: Pattern Matching `conn` in function call/2

How would you go about converting the code below from an if-else condition to case statements or private functions in an effort to replace imperative styled syntax with pattern matching?

I came across the following site that handled it using case statements: http://tensiondriven.github.io/posts/elixir-phoenix-redirect-after-authentication

Is there a better way?

1 Like
  def call(%{assigns: %{user: _}} = conn, _params), do: conn
  def call(conn, params) do
    conn
    |> put_flash(:error, "You must be logged in.")
    |> redirect(to: Helpers.topic_path(conn, :index))
    |> halt()
  end

Keep in mind that this assumes you would never have %{assigns: %{user: nil}}.

3 Likes

Thank you!

I’m still learning, and here’s what I understood from your code.

The 1st call/2 function signature (correct terminology?) pattern matches conn to a map of key assigns that has a value of another map with a key of user set to _ (pass all). If the match succeeds, the connection conn proceeds.

The 2nd call/2 function signature is a normal pattern in plug that will halt the connection, essentially stopping subsequent plugs, right?

Correct! Couple of minor clarifications.

It’s really just 1 function, with 2 clauses. A %Plug.Conn{} struct is a map (all structs are maps) so we can try to match on a user key set in the assigns key of the conn struct. If it matches then yup we just allow the conn to carry on.

If that first clause does not match we go to the second clause, which matches any conn. We know that this conn doesn’t have a user set because otherwise it would have gone to the first clause. Thus we set our error, and yeah halt the conn so that further plugs don’t end up running.

2 Likes