Sample Phoenix Framework Controller

Hi all! Happy New Year. I’ve been playing around recently with the Phoenix Framework quite a lot.
While I was learning it, I found myself wishing that a full-fledged example of a traditional MVC controller existed out there. I found a lot of this information in many different places.

Before we look at the controller, let’s look at a “changeset”. Changeset structs are passed into Ecto methods such as Repo.update and Repo.insert. It represents the delta of fields from the original object. This is something you define within your model, and it saves you a bunch of the trouble you would have converting all of the different pieces of information in your params hash into the appropriate datatypes. If you have any additional validations for that model, you can add them to the pipeline.

@required_fields ~w(number)
@optional_fields ~w(name)

def changeset(model, params \\ :empty) do
|> cast(params, @required_fields, @optional_fields)

This is pretty standard – if you have any other funky field types that don’t come standard with Ecto, such as file attachments handled with arc, this might have some additional methods.
The controller with standard REST routes will look like this:

defmodule MyApp.ThingController do
use MyApp.Web, :controller

alias MyApp.Thing
alias MyApp.Endpoint
alias MyApp.Repo
alias MyApp.Router.Helpers
require Logger
import MyApp.SessionController, only: [authenticate: 2]
import Ecto.Query, only: [from: 2]

plug :authenticate

def index(conn, _params) do
query = from a in Thing,
order_by: []
things = Repo.all(query)
render conn, "index.html", things: things

def show(conn, %{"id" => id}) do
render conn, "edit.html", thing: Repo.get!(Thing, id)

# Note: Changesets are used when we expect to change data
def edit(conn, %{"id" => id}) do
thing = Repo.get!(Thing, id)
render conn, "edit.html", changeset: Thing.changeset(thing)

def new(conn, _params) do
render conn, "new.html", changeset: Thing.changeset(%Thing{})

def create(conn, %{"thing" => thing_params}) do
Thing.changeset(%Thing{}, thing_params) |>
redirect conn, to: Helpers.thing_path(Endpoint, :index)

def update(conn, %{"id" => id, "thing" => thing_params}) do
Repo.get!(Thing, id) |>
Thing.changeset(thing_params) |>
redirect conn, to: Helpers.thing_path(Endpoint, :index)

def delete(conn, %{"id" => id}) do
Repo.get!(Thing, id) |>
redirect conn, to: Helpers.thing_path(Endpoint, :index)

Posted in Ecto, Elixir Tagged with: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *