Ошибка преднагрузки много ко многим в Ecto - PullRequest
0 голосов
/ 08 июня 2019
I am learning Ecto and was trying out many to many relationship.
I am using MySQL DB, 

схемы похожи на эти

Схема пользователя

  @primary_key {:id, :binary_id, autogenerate: true}
  schema "users" do
    field(:name, :string, required: true)
    field(:hashed_password, :string, required: true)
    field(:password, :string, virtual: true)
    timestamps()

    many_to_many(:methods, Bookie.Method.Model, join_through: "users_methods", on_replace: :delete)
  end

Схемы методов

  @primary_key {:id, :binary_id, autogenerate: true}
  schema "methods" do
    field(:function, :string, required: true)
    field(:method, :string, required: true)
    timestamps()

    many_to_many(:users, Bookie.User.Model, join_through: "users_methods", on_replace: :delete)
  end

ассоциация этих двух схем - users_methods


  schema "users_methods" do
    belongs_to(:users, Bookie.User.Model, type: :binary_id)
    belongs_to(:methods, Bookie.Method.Model, type: :binary_id)
  end

Это мои миграции

  create table(:users, primary_key: false) do
      add(:id, :uuid, primary_key: true)
      add(:name, :string, null: false)
      add(:hashed_password, :string, null: false)
      timestamps()
    end

   create(unique_index(:users, [:name]))

    create table(:methods, primary_key: false) do
      add(:id, :uuid, primary_key: true)
      add(:function, :string, null: false)
      add(:method, :string, null: false)
      timestamps()
    end

 create table(:users_methods, primary_key: false) do
      add(:user_id, references("users", type: :uuid, on_delete: :delete_all))
      add(:method_id, references("methods", type: :uuid, on_delete: :delete_all))
    end

    create(index(:users_methods, [:method_id]))
    create(index(:users_methods, [:user_id]))

    create(
      unique_index(:users_methods, [:user_id, :method_id], name: :user_id_method_id_unique_index)
    )

Это мои основные настройки.Теперь, как только я пытаюсь предварительно загрузить методы после запроса / вставки пользователя, он выдает ошибку.

  user_map = %{name: "User 1", password: "password"}

  changeset =
    User.changeset(%User{}, user_map)
    |> Ecto.Changeset.put_change(
      :hashed_password,
      User.hashed_password(changeset.changes[:password])
    )

  user =
    Repo.insert!(changeset)
    |> Repo.preload(:methods)

Ошибка


  [debug] QUERY OK db=2.6ms queue=0.1ms
begin []
[debug] QUERY OK db=3.5ms
INSERT INTO `users` (`hashed_password`,`name`,`inserted_at`,`updated_at`,`id`) VALUES (?,?,?,?,?) ["$2b$12$6W3zoeCnfLRV3N0fzv5t..LFnZly93G4IvfM5DfQSaEWPLtK0jV8q", "User 1", {{2019, 6, 8}, {14, 29, 25, 458464}}, {{2019, 6, 8}, {14, 29, 25, 458477}}, <<208, 210, 137, 42, 54, 3, 75, 211, 148, 173, 9, 174, 171, 125, 44, 225>>]
[debug] QUERY OK db=0.7ms
commit []
[debug] QUERY ERROR source="methods" db=29.5ms
SELECT m0.`id`, m0.`function`, m0.`method`, m0.`inserted_at`, m0.`updated_at`, u1.`id` FROM `methods` AS m0 INNER JOIN `users` AS u1 ON u1.`id` IN (?) INNER JOIN `users_methods` AS u2 ON u2.`model_id` = u1.`id` WHERE (u2.`model_id` = m0.`id`) ORDER BY u1.`id` [<<208, 210, 137, 42, 54, 3, 75, 211, 148, 173, 9, 174, 171, 125, 44, 225>>]
** (Mariaex.Error) (1054): Unknown column 'u2.model_id' in 'where clause'
    (ecto) lib/ecto/adapters/sql.ex:450: Ecto.Adapters.SQL.sql_call!/6
    (ecto) lib/ecto/adapters/sql.ex:420: Ecto.Adapters.SQL.do_execute/6
    (ecto) lib/ecto/repo/queryable.ex:133: Ecto.Repo.Queryable.execute/5
    (ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
    (elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2

(Mariaex.Error) (1054):Неизвестный столбец 'u2.model_id' в 'выражении where'

Я не получаю вышеуказанную часть: (

, пожалуйста, помогите кому-нибудь.

1 Ответ

1 голос
/ 08 июня 2019

Внешний ключ ассоциации отклоняется от последней части имени схемы. Поскольку все ваши схемы имеют имя Foo.Bar.Model, все они по умолчанию имеют значение model_id. Вы можете передать параметр join_keys, чтобы указать отношения.

Например:

many_to_many(:methods, Bookie.Method.Model, join_through: "users_methods", on_replace: :delete)

должно быть:

many_to_many(:methods, Bookie.Method.Model, join_through: "users_methods", join_keys: [user_id: :id, method_id: :id], on_replace: :delete)

И

many_to_many(:users, Bookie.User.Model, join_through: "users_methods", on_replace: :delete)

Должно быть:

many_to_many(:users, Bookie.User.Model, join_through: "users_methods", join_keys: [method_id: :id, user_id: :id], on_replace: :delete)

Хотя я бы порекомендовал следовать соглашению об именах Ecto, все станет намного проще.

...