Subscribe to access all episodes. View plans →

#154: Phoenix Verified Routes

Published November 21, 2022

Phoenix 1.7

Follow along with the episode starter on GitHub

Phoenix 1.7 introduces a new feature called Verified Routes. Verified Routes are a great feature that favors readability and they’re simpler to write. You no longer need to use a route helper function with a bunch of arguments, just the path you want to use. And because they’re compile-time checked you don’t have the headache that you normally would when using hardcoded strings.

Let’s see how to use them by re-writing a few of our links here to use Verified Routes.

We’ll update all the links on our album’s index page to use Verified Routes. Let’s open our app in an editor and we’ll go to our album’s index.html.heex template. Currently, for our links, we use the different Routes path helper functions that are generated, but with verified routes, we can simply write the path wrapped in the ~p macro.

Before we can re-write our links we need to see what the path is so let’s go to the command line and get a list of all our routes using the mix phx.routes command.

$ mix phx.routes
                  album_path  GET     /albums                                TeacherWeb.AlbumController :index
                  album_path  GET     /albums/:id/edit                       TeacherWeb.AlbumController :edit
                  album_path  GET     /albums/new                            TeacherWeb.AlbumController :new
                  album_path  GET     /albums/:id                            TeacherWeb.AlbumController :show
                  album_path  POST    /albums                                TeacherWeb.AlbumController :create
                  album_path  PATCH   /albums/:id                            TeacherWeb.AlbumController :update
                              PUT     /albums/:id                            TeacherWeb.AlbumController :update
                  album_path  DELETE  /albums/:id                            TeacherWeb.AlbumController :delete
                   page_path  GET     /                                      TeacherWeb.PageController :index
         live_dashboard_path  GET     /dashboard                             Phoenix.LiveDashboard.PageLive :home
         live_dashboard_path  GET     /dashboard/:page                       Phoenix.LiveDashboard.PageLive :page
         live_dashboard_path  GET     /dashboard/:node/:page                 Phoenix.LiveDashboard.PageLive :page
                              *       /dev/mailbox                           Plug.Swoosh.MailboxPreview []
                   websocket  WS      /live/websocket                        Phoenix.LiveView.Socket
                    longpoll  GET     /live/longpoll                         Phoenix.LiveView.Socket
                    longpoll  POST    /live/longpoll                         Phoenix.LiveView.Socket

Great - we can use these with our verified routes. Let’s start with the new album path. Then back in our template….we’ll wrap the route in the ~p.

Template path: lib/teacher_web/templates/album/index.html.heex

<span><.link href={~p"/albums/new"}>New Album</.link></span>

With our change let’s start the server.

$ mix phx.server

Great the app starts without any warnings so let’s go back to the browser - and our updated link works!

Alright, let’s go back to the template and update the other routes on our page. The links we have here - “show”, “edit”, and “delete” are a little different because they use the album variable to generate the URL path. Luckily to generate URLs that use named params is simpler with Verified Routes.

Instead of passing arguments into the route helper function, we’ll just grab the path that we want to use, and then this is simply interpolated with the ~p like a regular string, so we can add the album id to the path.

Template path: lib/teacher_web/templates/album/index.html.heex

<span><.link href={~p"/albums/#{}"}>Show</.link></span>

And if we go to the browser - great this works. Interpolated values like our “album” here are encoded via the Phoenix.Param protocol. So instead of using the - we can just use album.

Now let’s update the rest of the links here too. We’ll update the “edit” link and the “delete” link. Then let’s go to the command line and start the server. When we do we see that there’s a warning - there’s no path that matches one of our routes because we have a typo in our route. Because our URLs are now compile-time verified against your Phoenix router we’ll get these errors. Let’s go back to our template and fix the typo.

Template path: lib/teacher_web/templates/album/index.html.heex

<span><.link href={~p"/albums/#{album}"}>Show</.link></span>
<span><.link href={~p"/albums/#{album}/edit"}>Edit</.link></span>
<span><.link href={~p"/albums/#{album}"} method={:delete} data-confirm="Are you sure?">Delete</.link></span>

And starting our server again - that error is gone. Let’s go back to our browser one last time and we can see our “edit” link works and the “delete” link works too. Just like we wanted, all the links on our index page have been updated to use Phoenix’s new Verified Routes.

One thing that’s worth mentioning that we didn’t get to here is if you have something like a pagination link, you can use a keyword list or map of values and have them be interpolated with the ~p string.