Вставка несоответствия типов: двоичный_идентификатор с набором изменений Ecto

elixir phoenix-framework ecto

3070 просмотра

2 ответа

741 Репутация автора

У меня есть таблица applicationsс внешним ключом user_id, это Postgres uuid. Я имею в своем web.ex:

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

Моя модель:

defmodule Dashboard.Application do
  use Dashboard.Web, :model

  alias Dashboard.User
  alias Dashboard.Path

  schema "applications" do
    field :name, :string
    belongs_to :user, User
    has_many :paths, Path
    timestamps
  end

  @required_fields ~w(name user_id)
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

Но когда я пытаюсь сделать вставку с набором изменений, используя действующий uuid из моей usersтаблицы, я получаю

[error] #PID<0.407.0> running Dashboard.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /applications
** (exit) an exception was raised:
    ** (Ecto.ChangeError) value `<<184, 235, 134, 244, 95, 86, 74, 133, 159, 153, 31, 111, 16, 28, 76, 15>>` for `Dashboard.Application.user_id` in `insert` does not match type :binary_id
        (ecto) lib/ecto/query/planner.ex:33: anonymous fn/6 in Ecto.Query.Planner.fields/4
        (stdlib) lists.erl:1262: :lists.foldl/3
        (ecto) lib/ecto/query/planner.ex:21: Ecto.Query.Planner.fields/4
        (ecto) lib/ecto/repo/schema.ex:449: Ecto.Repo.Schema.dump_changes/5
        (ecto) lib/ecto/repo/schema.ex:77: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
        (ecto) lib/ecto/repo/schema.ex:477: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/9
        (ecto) lib/ecto/pool.ex:292: Ecto.Pool.with_rollback/3
        (ecto) lib/ecto/adapters/sql.ex:582: Ecto.Adapters.SQL.transaction/8
        (ecto) lib/ecto/pool.ex:244: Ecto.Pool.outer_transaction/6
        (ecto) lib/ecto/adapters/sql.ex:551: Ecto.Adapters.SQL.transaction/3
        (dashboard) web/controllers/application_controller.ex:16: Dashboard.ApplicationController.create/2

Осматривая user_idя вижу:

pry(1)> params["user_id"] |> i
Term
  <<184, 235, 134, 244, 95, 86, 74, 133, 159, 153, 31, 111, 16, 28, 76, 15>>
Data type
  BitString
Byte size
  16
Description
  This is a binary: a collection of bytes. It's printed with the `<<>>`
  syntax (as opposed to double quotes) because it is not a
  UTF-8 encoded binary (the first invalid byte being `<<184>>`)
Reference modules
  :binary

Похоже, он пытается вставить действительный 16-байтовый UUID для меня. Что мне не хватает? Спасибо!

ОБНОВЛЕНИЕ: Вот схема БД:

              Table "public.applications"
   Column    |            Type             | Modifiers
-------------+-----------------------------+-----------
 id          | uuid                        | not null
 user_id     | uuid                        | not null
 name        | text                        | not null
 inserted_at | timestamp without time zone | not null
 updated_at  | timestamp without time zone | not null
Indexes:
    "applications_pkey" PRIMARY KEY, btree (id)
    "applications_user_id_index" btree (user_id)
Foreign-key constraints:
    "applications_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
Referenced by:
    TABLE "paths" CONSTRAINT "paths_application_id_fkey" FOREIGN KEY (application_id) REFERENCES applications(id) ON DELETE CASCADE

                 Table "public.users"
   Column    |            Type             | Modifiers
-------------+-----------------------------+-----------
 id          | uuid                        | not null
 email       | text                        | not null
 inserted_at | timestamp without time zone | not null
 updated_at  | timestamp without time zone | not null
 avatar      | text                        | not null
 name        | text                        | not null
 data        | jsonb                       | not null
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
    "users_email_index" UNIQUE, btree (email)
Referenced by:
    TABLE "applications" CONSTRAINT "applications_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE

Обновление 2: я обновился до Phoenix 1.2 и ecto 2.0.2, и проблема остается

Обновление 3: я думаю, что это может быть ошибка в Ecto. Я открыл PR с моей лучшей попыткой исправить: https://github.com/elixir-ecto/ecto/pull/1585

Автор: Brad Urani Источник Размещён: 18.07.2016 01:41

Ответы (2)


3 плюса

31 Репутация автора

Проверьте файл миграции и убедитесь, что вы определяете правильный тип данных для поля id.

add :user_id, references(:users, type: :uuid)

Автор: Well Ronfim Размещён: 06.04.2017 08:33

6 плюса

3868 Репутация автора

Решение

При использовании схем Ecto binary_idожидается, что данные будут представлять собой UUID в формате String, который затем автоматически преобразуется в 16-байтовый двоичный формат Ecto.

Если вы хотите работать с двоичным представлением напрямую, вы можете определить тип как :binary_id

schema "applications" do
  field :name, :string
  belongs_to :user, User, foreign_key: :user_id, type: :binary_id
  has_many :paths, Path
  timestamps
end

Также можно преобразовать двоичные данные в строку с помощью Ecto.UUID.load:

iex(38)> binary = Ecto.UUID.bingenerate()
<<91, 154, 58, 233, 38, 235, 76, 200, 188, 162, 112, 23, 233, 223, 191, 144>>
iex(39)> Ecto.UUID.load(binary)
{:ok, "5b9a3ae9-26eb-4cc8-bca2-7017e9dfbf90"} 
Автор: Mike Buhot Размещён: 20.04.2017 09:43
Вопросы из категории :
32x32