© 2020 WebHive

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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. Добавляем соответствующую конструкцию:

1
2
3
4
5
6
7
8
9
10
11
12
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 в параметры связи

1
2
3
4
5
6
7
8
9
10
11
12
13
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

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

Источники

Комментарии