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
.