ectoでsoft deletionを実装する流れについてまとめます。
Phoenixで新しいコンテキストを作成するときに論理削除をつける手順が多いため、毎回毎回調べるのが面倒でした。今後の作業が楽になればと思ってます。
以下例としてブログ作成をした際にPostスキーマに論理削除をつけます。
楽をしたい場合はライブラリを使用できます😂
コンテキストをLiveViewとして作成
mix phx.gen.live Blog Post posts title body deleted_at:datetime
スキーマファイルにdelete_changesetを追加
myapp/blog/post.ex
defmodule MyApp.Blog.Post do
use Ecto.Schema
import Ecto.Changeset
schema "posts" do
field :body, :string
field :title, :string
field :deleted_at, :naive_datetime
timestamps()
end
@doc false
def changeset(post, attrs) do
post
|> cast(attrs, [:title, :body]) # <- do not include :deleted_at
|> validate_required([:title, :body]) # <- do not include :deleted_at
end
@doc false
def delete_changeset(post, attrs) do
post
|> cast(attrs, [:deleted_at])
|> validate_required([:deleted_at])
end
end
Soft Deleteされたエントリがクエリされないようにコンテキストファイルを変更する
myapp/blog/post.ex
defmodule MyApp.Blog do
import Ecto.Query, warn: false
alias MyApp.Repo
alias MyApp.Blog.Post
def list_posts do
query = from p in Post, where: is_nil(p.deleted_at) # <- added
Repo.all(query)
end
def get_post!(id) do
query = from p in Post, where: is_nil(p.deleted_at) # <- added
Repo.get!(query, id)
end
...
def delete_post do
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) # <- added
post
|> Post.delete_changeset(%{deleted_at: now})
|> Repo.update() # <- altered to update
end
end
Soft Deletionの是非
しかし論理削除はデータベースのデータベース専門の方々からはあまり好意的ではない意見が散見され、是非が問われているようです。
ユーザーがデータを削除したいというニーズに応えるにはどのようなDB設計をするのが正解なのかがよくわからんです。