© 2026 WebHive

Используем UUID в качестве первичного ключа в моделях Phoenix

Появилась задача — использовать в качестве первичного ключа таблицы в проекте на Phoenix поле с UUID-ом. Как оказалось в Phoenix существует готовое решение, которое к тому же ещё и нормально работает и позволяет решить задачу с минимальными усилиями.

Итак первым делом очевидно нужно что-то добавить в миграцию — указыаем, что у нас нет первичного ключа, чтобы отключить его автогенерацию и добавляем соответствующее поле.

defmodule MyApp.Repo.Migrations.CreatePerson do
  use Ecto.Migration

  def change do
    create table(:people, primary_key: false) do
      add :id, :uuid, primary_key: true, default: fragment("uuid_generate_v4()")
      add :name, :string

      timestamps
    end

  end
end

Ну и затем нужно как-то сказать модели, чтобы в качестве идентификатора у нас генерировался UUID. Добавляем соответствующую конструкцию:

defmodule MyApp.Person do
  use MyApp.Web, :model

  # :binary_id генерируетс драйвером, по умолчанию для postgres это UUID
  @primary_key {:id, :binary_id, autogenerate: true}

  schema "people" do
    field :name, :string

    timestamps
  end
...

Запускаем миграцию и видим, что поле у нас теперь типа uuid, и при сохранении модели первичный ключ генерируется как UUID.

При создании связей в таблице с использованием UUID первичного ключа необходимо добавить type: :uuid в параметры связи

defmodule MyApp.Repo.Migrations.CreateTask do
  use Ecto.Migration

  def change do
    create table(:tasks) do
      add :name, :string
      add :person_id, references(:people, type: :uuid)

      timestamps
    end

  end
end

Крайне удивлён. Всё прошло настолько гладко, что до сих пор не покидает ощущение какого-то подвоха. Но чорт побери — оно работает!

Источники

Комментарии