Building an Action

Learn about how to generate boilerplate HTML and how to set routes in phoenix.

Building the Phoenix application

The first thing we’ll need is a simple way to list all the menu items we have in our system so we can then take further action. If you aren’t familiar with server-side rendering in Phoenix, don’t worry. We’ll cover everything we need to know here. In order to avoid writing a ton of HTML boilerplate, we’ll use one of the Phoenix generators, and then replace the generated controller contents as needed.

Press + to interact
mix phx.gen.html --no-context --no-schema Menu Item items
rm test/plate_slate_web/controllers/item_controller_test.exs

The first command generates some boilerplate HTML for us, and the second removes a test case we don’t need. Up next is our router. We’ll use the :browser pipeline that’s unused so far by creating an /admin scope inside which we’ll set up our controller:

Press + to interact
scope "/admin", PlateSlateWeb do
pipe_through :browser
resources "/items", ItemController
end

Routes configuration

We can confirm that our router is properly set up by using the handy mix phx.routes command:

Press + to interact
mix phx.routes
* /api Absinthe.Plug [schema: PlateSlateWeb.Schema]
* /graphiql Absinthe.Plug.GraphiQL [...]
item_path GET /admin/items PlateSlateWeb.ItemController :index
item_path GET /admin/items/:id/edit PlateSlateWeb.ItemController :edit
item_path GET /admin/items/new PlateSlateWeb.ItemController :new
item_path GET /admin/items/:id PlateSlateWeb.ItemController :show
item_path POST /admin/items PlateSlateWeb.ItemController :create
item_path PATCH /admin/items/:id PlateSlateWeb.ItemController :update
PUT /admin/items/:id PlateSlateWeb.ItemController :update
item_path DELETE /admin/items/:id PlateSlateWeb.ItemController :delete

We can now turn our attention to the controller, where we’ll replace its existing contents entirely with the following:

Press + to interact
defmodule PlateSlateWeb.ItemController do
use PlateSlateWeb, :controller
use Absinthe.Phoenix.Controller,
schema: PlateSlateWeb.Schema
end

Now for the fun part. The Absinthe.Phoenix.Controller gives us a way to associate a GraphQL query with a controller action. We can use the data that was looked up from that query in our controller. We won’t replace the controller actions, but rather augment them by utilizing all the lookup abilities we’ve already written. This lets our controller focus on just managing the HTTP connection. Let’s start with something basic:

Press + to interact
@graphql """
{
menu_items {
name
}
}
"""
def index(conn, result) do
result |> IO.inspect
render(conn, "index.html", items: result.data["menu_items"] || [])
end

Let’s break this down. At the top of this snippet is a @graphql module attribute on which we’re putting a string with a GraphQL query. Beneath that there’s a relatively ordinary-looking Phoenix controller callback index/2. This controller gets the HTTP conn and some params. Then, it renders an index.html. At a high level, the controller action acts ...