jdj_dk

jdj_dk

Nesting Ecto.Multis

Hi all you lovely people

I have a situation where I have to import a data set with multiple items where each has some other items associated with them.
To do this I’ve created a nested Ecto.Multi where the outer one map through all items a each time creates and execute an Ecto.Multi.new

A part of the code can be seen below:

def import_issues(issues, %Pace.GitRepository{board: board = %Pace.Board{}} = git_repository) do
    Ecto.Multi.new
    |> Ecto.Multi.run(:insert_issues, fn(_) ->
      issues
      |> Enum.map(&insert_data_for_issue(&1, board, git_repository))
      |> all_ok?
    end)
    |> Repo.transaction
  end

  defp insert_data_for_issue(%Pace.Bitbucket.Issue{} = issue, board, git_repository) do
    column = find_board_column(board, issue)
    reporter_user = Pace.Accounts.find_by_token_uuid(issue.reporter.uuid)
    card_params = prepare_card_params(issue, board, git_repository)

    Ecto.Multi.new
    |> create_card(reporter_user, column, card_params)
    |> create_remote_issue(issue, git_repository)
    |> create_comments(issue, board, git_repository)
    |> Repo.transaction
  end

This is all well and fine until I started making negative tests forcing the inner transaction to fail. This creates the following error:

** (CaseClauseError) no case clause matching: {:error, :rollback}
	      (ecto) lib/ecto/repo/queryable.ex:21: Ecto.Repo.Queryable.transaction/4
	      (espec) lib/espec/example_runner.ex:205: ESpec.ExampleRunner.do_run_before/2
	      (espec) lib/espec/example_runner.ex:138: anonymous fn/3 in ESpec.ExampleRunner.run_befores_and_lets/1
	      (espec) lib/espec/example_runner.ex:176: ESpec.ExampleRunner.call_with_rescue/2
	      (elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3
	      (espec) lib/espec/example_runner.ex:136: ESpec.ExampleRunner.run_befores_and_lets/1
	      (espec) lib/espec/example_runner.ex:37: ESpec.ExampleRunner.run_example/2
	      (espec) lib/espec/suite_runner.ex:76: ESpec.SuiteRunner.spawn_task/0

I assume this is due to the outer Ecto.Multi expecting error tuples to look like {:error, _} but it is getting {:error, failed_operation, failed_value, changes_so_far}. So my question is, how does one go about solving this? Can one not nest Ecto.Multi like this? And if that is the case, how should I go about this challenge?

Should I instead look into appending Ecto.Multi together?

Most Liked

jdj_dk

jdj_dk

The error came from my all_ok? function which maps all results from map to find a single :error tuple. Fixing this made the nested structure work fine.

Where Next?

Popular in Questions Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

Other popular topics Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

We're in Beta

About us Mission Statement