rbino

rbino OP

Ash Core Team

I’m finding myself working with Ecto.Multi more and more recently, and I’m trying to understand what are the best practices to work with them.

My question for this topic is: what is the suggested approach to factor out a common Multi operation that you want to execute in multiple places?

The approaches I’m aware of are:

Creating a function that accepts a Multi and returns a Multi

Example:

def create_foo(attrs) do
  Multi.new()
  |> Multi.insert(:foo, Foo.changeset(%Foo{}, attrs))
  |> associate_foo_with_bars()
  |> ...
end

def update_foo(foo, attrs) do
  Multi.new()
  |> Multi.insert(:foo, Foo.changeset(foo, attrs))
  |> associate_foo_with_bars()
  |> ...
end

defp associate_foo_with_bars(multi) do
  multi
  |> Multi.update_all(...)
end

Extracting the function you pass as argument to Multi.whatever

Example:

def create_foo(attrs) do
  Multi.new()
  |> Multi.insert(:foo, Foo.changeset(%Foo{}, attrs))
  |> Multi.update_all(:associate, &associate_foo_with_bars/1, [])
  |> ...
end

def update_foo(foo, attrs) do
  Multi.new()
  |> Multi.insert(:foo, Foo.changeset(foo, attrs))
  |> Multi.update_all(:associate, &associate_foo_with_bars/1, [])
  |> ...
end

defp associate_foo_with_bars(%{foo: foo}) do
   from b in Bars,
     ...
end

Using Multi.merge

def create_foo(attrs) do
  Multi.new()
  |> Multi.insert(:foo, Foo.changeset(%Foo{}, attrs))
  |> Multi.merge(&associate_foo_with_bars/1)
  |> ...
end

def update_foo(foo, attrs) do
  Multi.new()
  |> Multi.insert(:foo, Foo.changeset(foo, attrs))
  |> Multi.merge(&associate_foo_with_bars/1)
  |> ...
end

defp associate_foo_with_bars(%{foo: foo}) do
  Multi.new()
  |> Multi.update_all(:associate, ...
    from b in Bars,
      ...
  end)
end

I’m interested in the pros and cons of the approaches (and possibly to other approaches), and what approach you think works best for specific situations.

Moreover, I’d like to know if you consider the name of the operations part of the API to compose your Multis.
I’ll expand on what I mean: in examples 2 and 3 above, my function accepts changes, and I assert that there’s a :foo key that contains the Foo I need to use in the next operation.
Another approach could be pattern match on :foo in the top Multi and just pass the Foo struct to the functions, that would not be coupled to the operation name.
Do you accept the whole changes map in your Multi composition function or the single result of an operation?


Please note the aim of threads like this is for you to explain things in your own words. Please see this thread for details :slight_smile: (videos/links to further reading are also welcome though!)

First Post! Switch mode

Pavij

Pavij

I’m also interested in this topic!

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New

We're in Beta

About us Mission Statement