Playing With Fire

Exploring the web one Elixir at a time

Building a Blog with Phoenix (Part 2)

As I had a spare hour, I thought that I would continue on with the ‘Build a blog’ series. As a continuation from where we left off last time, I thought that I would tackle the issue of publishing. For those of you that like to follow along, but haven’t set up the blog yet, read Building a Blog with Phoenix to get started.


Adding in a Publish button

The first thing that will need to happen is that the router will need to be updated with a new route. As this will require that the data in the Post model is updated, we will use the PUT HTTP verb as follows

scope "/", Blog do
    pipe_through :browser # Use the default browser stack

    put "/posts/:id/publish", PostController, :publish      <--- Add this line
    resources "/posts", PostController
    get "/:url", ArticleController, :show
    get "/", ArticleController, :index

Once this is in place, update the Post Controller by adding in a new publish action

def publish(conn, %{"id" => id}) do
    post = Repo.get!(Post, id)
    changeset = Post.changeset(post, %{"published" =>  true, "date_published" => Ecto.Date.utc})

    case Repo.update(changeset) do
      {:ok, post} ->
        |> put_flash(:info, "Published successfully.")
        |> redirect(to: post_path(conn, :show, post))
      {:error, _} ->
        |> put_flash(:error, "Didn't publish")
        |> redirect(to: post_path(conn, :show, post))

Here we are passing the Post Id in the PUT request. Using this data, we are pulling the associated record into a changeset and updating it. We will cover data validation shortly. On successful update, we’ll add a ‘Success’ message to the page flash and redirect back to the Show action. On fail, we’ll do the same but with a different message.

The last thing that needs to happen is that the Show template (web/templates/post/show.html.eex) needs to be updated.

We do this as follows - to the bottom of the meta data section

    <div class="col-sm-2">
      <p class="small">Last Updated:</p>
    <div class="col-sm-2">
      <%= date_format @post.updated_at %>
  <p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>    <-- Add this line
  <p class="danger danger-info" role="alert"><%= get_flash(@conn, :info) %></p>  <-- And this one

And then, add in the button at the bottom of the page

<section class="control">
  <%= if not @post.published do %>
    <%= link "Publish", to: post_path(@conn, :publish, @post), method: :put, class: "btn btn-danger" %>
  <% end %>

And thats it, you can now preview and publish from the same page.