LoginSignup
8
3

More than 3 years have passed since last update.

Phoenixで論理削除②:削除UIのトグル化

Last updated at Posted at 2021-03-06

Elixir Digitalization Implementors/fukuoka.ex/kokura.exのpiacereです
ご覧いただいて、ありがとうございます :bow:

前回は、Phoenixのphx.gen.html/phx.gen.jsonで生成されるDBアクセッサの「論理削除」を実装したので、今回は、削除UIの論理削除トグル化の対応を行います

内容が、面白かったり、役に立ったら、「LGTM」よろしくお願いします :wink:

:ocean::ocean::ocean: Advent Calendar、fukuoka.ex1位、Elixir2位達成ヽ(=´▽`=)ノ :ocean::ocean::ocean:

fukuoka.ex Advent Calendar、Webテクノロジーカテゴリで堂々1位 … 各コラムぜひお読みください
https://qiita.com/advent-calendar/2020/fukuokaex
image.png

そして、プログラミング言語カテゴリは、1位がRust、2位がElixir、3位がGoとモダン言語揃い踏みでのトップ3、熱いネー:laughing:
https://qiita.com/advent-calendar/2020/elixir
image.png

本コラムの検証環境

本コラムは、以下環境で検証しています(Windowsで実施していますが、Linuxやmacでも動作する想定です)

削除UIの論理削除対応

一覧UIのDeleteリンクが、前回の対応により、物理削除から、論理削除に変更されていますが、一度Deleteした後は、論理削除状態を解除して、元に戻すことができないUIになっています
image.png

これを、論理削除状態をトグル化するために、コントローラを改修します

改修前のコントローラは、以下の通りです

lib/basic_web/controllers/post_controller.ex
defmodule BasicWeb.PostController do
  use BasicWeb, :controller

  def delete(conn, %{"id" => id}) do
    post = Posts.get_post!(id)
    {:ok, _post} = Posts.delete_post(post)

    conn
    |> put_flash(:info, "Post deleted successfully.")
    |> redirect(to: Routes.post_path(conn, :index))
  end

これを以下のように、対象データの論理削除状態で、呼び出す関数と、実行後のメッセージをスイッチするように改修します

lib/basic_web/controllers/post_controller.ex
  def delete(conn, %{"id" => id}) do
    post = Posts.get_post!(id)
#    {:ok, _post} = Posts.delete_post(post)  # Comment-out here

    # Add start
    action = case post.deleted_at do
      nil -> %{ target: "deleted",         func: &Posts.delete_post/1 }
      _   -> %{ target: "delete restored", func: &Posts.restore_delete_post/1 }
    end
    {:ok, _post} = action.func.( post )
    # Add end

    conn
#    |> put_flash(:info, "Post deleted successfully.")  # Comment-out here
    |> put_flash(:info, "Post #{ action.target } successfully.")  # Add here
    |> redirect(to: Routes.post_path(conn, :index))
  end

一覧UIのDeleteリンク文言も、論理削除状態でスイッチするようにします

lib/basic_web/templates/post/index.html.eex

<%= for post <- @posts do %>
    <% logical_delete = if post.deleted_at == nil, do: "Delete", else: "Restore"  # Add here %>
    <tr>
      <td>
        <span><%= link "Show", to: Routes.post_path(@conn, :show, post) %></span>
        <span><%= link "Edit", to: Routes.post_path(@conn, :edit, post) %></span>
        <!-- <span> --><%= # Comment-out after link "Delete", to: Routes.post_path(@conn, :delete, post), method: :delete, data: [confirm: "Are you sure?"] %><!-- </span> -->
        <span><%= link logical_delete, to: Routes.post_path(@conn, :delete, post), method: :delete, data: [confirm: "Are you sure?"] %></span>  <!-- Add here -->
      </td>
    </tr>
<% end %>

これで、Deleteリンクをクリックすると、下記の通り、deleted_atに現在日時(UTC)が入り、DeleteリンクがRestoreリンクにスイッチするようになります
image.png

Restoreリンクをクリックすると、deleted_atが空(nil)になり、RestoreリンクがDeleteリンクに戻ります
image.png

最後に

今回は、削除UIの論理削除トグル化を行いました

Elixir開発の実務でも良く出てくるテクニックなので、覚えておきましょう

次回は、一覧/個別表示UIでの論理削除時グレーアウト表示切り替えを行います

p.s.このコラムが、面白かったり、役に立ったら…

image.pngimage.png にて、どうぞ応援よろしくお願いします:bow:

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3