#elixir #phoenix-framework #ecto
#elixir #phoenix-framework #ecto
Вопрос:
В схеме Ecto можно указать автоматически созданный первичный ключ с помощью @primary_key
атрибута:
@primary_key {:id, :binary_id, autogenerate: true}
Есть ли способ указать пользовательскую функцию для autogenerate
? Я полагаю, что в этом случае он будет использовать Ecto.UUID.generate
, тогда как я хотел бы использовать UUID v1.
Ответ №1:
Согласно официальной документации, вы можете создать свой собственный первичный ключ.
Вот краткий пример для установки name
в качестве первичного ключа:
допустим, мы сгенерировали Player
таблицу со следующей задачей смешивания :
mix phoenix.gen.json Player players name:string position:string number:integer
при миграции установите create table
с помощью primary_key: false
и добавьте primary_key: true
в поле имя :
def change do
create table(:players, primary_key: false) do
add :name, :string, primary_key: true
add :position, :string
add :number, :integer
timestamps
end
end
Затем в вашей схеме все, что вам нужно сделать, это сообщить Ecto, что первичный ключ теперь является строкой ( @primary_key {:name, :string, []}
) и что идентификатор, который будет использоваться (например, в маршрутах), будет name
@derive {Phoenix.Param, key: :name}
. Также не забудьте удалить field :name, :string
.
defmodule Hello.Player do
use Hello.Web, :model
@primary_key {:name, :string, []}
@derive {Phoenix.Param, key: :name}
schema "players" do
field :position, :string
field :number, :integer
timestamps
end
Что вы можете сделать в вашем случае, так это настроить свое собственное поле в качестве первичного ключа, а затем заполнить его в наборе изменений с помощью метода, который генерирует идентификатор с UUID v1, когда вы сохраняете свои данные в своей базе данных.
Вы можете воспользоваться пакетом UUID, который имеет метод UUID v1.
Не уверен, что это лучшее обходное решение, но я надеюсь, что это поможет вам 🙂
Комментарии:
1. Это имеет смысл, спасибо. Я знаю, что могу установить пользовательский идентификатор в каждом наборе изменений, но поскольку это то, что я хотел бы сделать для всех схем во всех наборах изменений, которые создают новую запись, я надеюсь найти способ настроить функцию генерации пользовательского идентификатора в одном месте для всего …
2. @FeifanZ вы нашли лучшее решение этой проблемы? Мне любопытно, как вы справились с этим 🙂
3. Я не нашел лучшего решения этой конкретной проблемы, но вместо этого нашел альтернативный подход. Изначально я думал, что мне нужен UUID v1 для сортировки, но оказывается, что мне это строго не нужно, поэтому UUID v4 в порядке.
Ответ №2:
Вот мое решение
#Custom string type (example of Ecto.UUID)
defmodule Ecto.UUID.AutoGenerate do
use Ecto.Type
def type, do: :string
def cast(uuid), do: {:ok, uuid}
def dump(uuid), do: {:ok, uuid}
def load(uuid), do: {:ok, uuid}
def autogenerate, do: Ecto.UUID.generate() # <- update your version here
end
# In your schema
defmodule PosService.Weathers.Weather do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, Ecto.UUID.AutoGenerate, autogenerate: true}
@foreign_key_type :string
schema "weathers" do
field :city, :string
field :prcp, :float
field :temp_hi, :integer
field :temp_lo, :integer
timestamps()
end
end