JavaScriptを有効にしてください

【Elixir】Ecto.Repoを拡張してSoft Deleteされていないレコードだけを取得する方法

 ·  ☕ 3 分で読めます

【Elixir】Ecto.Repoを拡張してSoft Deleteされていないレコードだけを取得する方法

ElixirのEcto.Repoを拡張して、Soft Delete(deleted_at is nil)されていないレコードだけを効率的に取得する方法について解説します。

はじめに

Soft Deleteはデータベースのレコードを物理的には削除せず、deleted_atフィールドにタイムスタンプを設定することで削除されたとみなします。
この記事では、Ecto.Repoにカスタム関数を追加することで、このようなレコードを簡単に取得する方法を紹介します。

確認環境

  • Elixir 1.14.2
  • Phoenix 1.6.3

方法1: モジュール拡張で関数を追加

Ecto.Repoを使用するモジュールに直接カスタム関数を追加します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
defmodule MyApp.Repo do
  use Ecto.Repo, otp_app: :my_app
  import Ecto.Query  # Ecto.Queryをインポート

  # Soft Deleteされていないレコードを取得するカスタム関数
  def get_active(queryable) do
    # deleted_atがnilのレコードだけをフィルタ
    query = from q in queryable, where: is_nil(q.deleted_at)
    # クエリを実行
    all(query)
  end
end

使用例

1
2
# MyApp.ItemからSoft Deleteされていないレコードを取得
active_items = MyApp.Repo.get_active(MyApp.Item)

方法2: デリゲーションで関数を追加

別のモジュールで関数を定義し、Repoモジュールでデリゲートします。

デリゲーションとは?

デリゲーション(委譲)とは、あるモジュールの関数を別のモジュールで利用できるようにするプログラミングテクニックです。Elixirでは、defdelegateマクロを使用して簡単にデリゲーションを実装できます。

このテクニックは、コードの再利用性を高めるだけでなく、モジュールの責任を明確に分けるのにも役立ちます。

デリゲーション元の関数を作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
defmodule MyApp.CustomRepoFunctions do
  import Ecto.Query  # Ecto.Queryをインポート

  # Soft Deleteされていないレコードを取得するカスタム関数
  def get_active(queryable) do
    # deleted_atがnilのレコードだけをフィルタ
    query = from q in queryable, where: is_nil(q.deleted_at)
    # クエリを実行
    MyApp.Repo.all(query)
  end
end

デリゲートします。

1
2
3
4
5
6
defmodule MyApp.Repo do
  use Ecto.Repo, otp_app: :my_app

  # MyApp.CustomRepoFunctionsの関数をデリゲート
  defdelegate get_active(queryable), to: MyApp.CustomRepoFunctions
end

使用例

1
2
# MyApp.ItemからSoft Deleteされていないレコードを取得
active_items = MyApp.Repo.get_active(MyApp.Item)

方法3 モジュールの使用

一応モジュールが用意されているようなのでモジュールを入れたら可能なようです。
ecto_soft_delete

まとめ

ElixirとEctoを使用して、deleted_at is nilのレコードだけを効率的に取得する方法はいくつかあります。
システムの方針に合わせて拡張性やメンテナンス性を考えて実装をしてください。

共有

こぴぺたん
著者
こぴぺたん
Copy & Paste Engineer