Phoenix Plug and Sessions

As I dive more into Elixir and the Phoenix framework I got to play with sessions and plug. I've been building a simple shopping cart app as a learning exercise.

In a typical shopping cart you need some way to save the state of the users shopping cart as they move around the site, and have access to that data on many pages. I solved this by persisting their "cart" in the DB and then storing the ID of that record in their session. I then used a custom plug to check their session for the ID or create it if nil.

Here is the plug.


# phoenix_cart/lib/phoenix_cart/plugs/cart.ex

defmodule PhoenixCart.Plugs.Cart do
  import Plug.Conn
  alias PhoenixCart.Repo
  alias PhoenixCart.Order

  def init(default), do: default

  def call(conn, _default) do
    if get_session(conn, :cart) do
      cart = Repo.get(Order, get_session(conn, :cart))
      assign(conn, :order, cart)
    else
      cart = Repo.insert!(%Order{status: "cart"})
      conn = put_session(conn, :cart, cart.id)
      assign(conn, :order, cart)
    end
  end
end

When the plug is called it checks the users sessions for what is stored in the :cart key. If found it finds that order record in the repo then assigns it into the connection.

If the :cart key returns nil then it creates a new order too act as that users cart, records it's id in the session under the :cart key, and then assign the order to the connection.

Now that the plug is ready we can "plug" it into any controller actions where the app will need access to the cart.

plug PhoenixCart.Plugs.Cart when action in [:index, :show]  

That's all there is too it, we now have a module plug that we can use to transform the connection where ever is needed, and how to maintain state using cookie sessions.