Вставка внешнего ключа от построения ассоциации с заданной схемой в одной транзакции - PullRequest
1 голос
/ 24 июня 2019

У меня есть схема exchange_accounts и user_profile user_profile имеет столбец foreign_key exchange_accounts_id, на который ссылается схема exchange_accounts. Я хочу вставить данные в таблицу user_profile, для которой мне нужно связать exchange_accounts_id со столбцом первичного ключа таблицы exchange_accounts.

У меня есть create_user_profile функция я попробовал, используя Ecto.Multi.run Сейчас я не понимаю, как строить связь между ними.

def create_user_profile(profile_info, dealer_id) do
   Ecto.Multi.new()
    |> Ecto.Multi.run(:exchange, fn %{exchange: exchange} -> Ecto.build_assoc(exchange, :user_profile)
    |> Ecto.Multi.insert(:user, UserProfile.changeset(%UserProfile{}, profile_info))
    |> Ecto.Multi.merge(fn %{user: user} ->
      bank_detail =
        Ecto.build_assoc(user, :bank_details)
        |> BankDetails.changeset(profile_info)

      Ecto.Multi.new()
      |> Ecto.Multi.insert(:bank_detail, bank_detail)
    end)

я хочу сделать это перед вставкой данных в таблицу user_profile И я попытался сделать это, используя Ecto.Multi.run, но он не работает.

результатом должно быть построение ассоциации между таблицами и вставка данных. Когда я пытаюсь запустить его, он не собирается идти в сторону только этого помазания. я не понимаю, где я неправ, и использование Ecto.Multi.run является правильным или нет.

1 Ответ

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

Ecto.Multi.run/3/5 само по себе ничего не сделает, вам все равно нужно выполнить какие-либо операции внутри fn/2, который вы передаете. Эта функция должна возвращать либо {:ok, val} для того, что вы считаете успешной операцией, либо {:error, val}, если вы считаете, что операция завершилась неудачей, так что Ecto знает, следует ли выполнить откат или нет всей транзакции.

Начиная с> Ecto 3 (если я не ошибаюсь), Multi insert, update и т. Д. Также могут принимать fn/1, где аргументом пока будет карта нескольких операций.

Так что вы, вероятно, должны изменить это: |> Ecto.Multi.run(:exchange, fn %{exchange: exchange} -> Ecto.build_assoc(exchange, :user_profile)

до:

|> Ecto.Multi.insert(:exchange, fn(_) -> Ecto.build_assoc(exchange, :user_profile) end)

или держи бег, но сделай:

Ecto.build_assoc(exchange, :user_profile)
|> Repo.insert()

А затем на пользовательской вставке используйте значение :exchange, чтобы поместить его в свой user_profile.

|> Ecto.Multi.insert(:user, fn(%{exchange: exchange}) ->
  # now you have access to the `exchange` operation result from the previous step
  UserProfile.changeset(%UserProfile{}, profile_info)
end)

Вы также можете запустить все это как обычный код внутри Repo.transaction/1, выполнив обычные Repo.insert и т. Д. Внутри передаваемого ему закрытия fn. Multi позволяет вам явно разделять каждую операцию и получать доступ к каждой из них на каждом последующем шаге, делать другие вещи, которые могут или не могут измениться, если вы считаете транзакцию успешной (даже если она не связана с операциями БД) или нет, и возвращаться успешно или с ошибочной операцией и т. д., а также передачей структуры Multi для добавления других вещей через Multi.merge.

...