Ecto.Multi.run/3 - how to use it correctly

I’m on my learning curve of Phoenix and following the Phoenix For Rails developers book. It seems like it is a little bit outdated and the following line raises the error when running the test:

1) test orders process_order/3 creates an order (Storex.SalesTest)
     test/storex/sales/sales_test.exs:132
     ** (FunctionClauseError) no function clause matching in Ecto.Multi.run/3

     The following arguments were given to Ecto.Multi.run/3:
     
         # 1
         %Ecto.Multi{names: #MapSet<[]>, operations: []}
     
         # 2
         :order
     
         # 3
         #Function<3.77911555/1 in Storex.Sales.process_order/3>
     
     Attempted function clauses (showing 1 out of 1):
     
         def run(multi, name, run) when is_function(run, 2)
     
     code: {:ok, order} = Sales.process_order(user, cart, %{address: "Test Street, 25"})
     stacktrace:
       (ecto) lib/ecto/multi.ex:436: Ecto.Multi.run/3
       (storex) lib/storex/sales/sales.ex:68: Storex.Sales.process_order/3
       test/storex/sales/sales_test.exs:139: (test)

Being in the very beginning of the learning, it is not really clear what the error says. Any idea?
I’m using:

  • Elixir 1.9.1
  • phoenix, “~> 1.4.10”
  • phoenix_ecto, “~> 4.0”
  • ecto_sql, “~> 3.1”

Thank you.

The function you are passing to the run probably doesn’t take 2 arguments, remember that the documentation states that it takes a function of two arguments, the first is the repo, the second is the resolved multi up to that point. So you probably just need to add a _repo, at the front of the argument list of the function that is being run I’d guess.

You can see that via here:

 #Function<3.77911555/1 in Storex.Sales.process_order/3>

It takes 1 argument, not two, yet you see it requires 2 here:

def run(multi, name, run) when is_function(run, 2)
2 Likes

On mobile and don’t have links handy but I’m 99% sure that if you look at the upgrade guide from ecto 2.x to 3.x you will see a change to the Ecto Multi calls that you should implement in your code.

4 Likes