Ecto Multi using `repo` and not `Repo`

I read this on https://smartlogic.io/blog/introduction-to-ecto-multi/ I wonder how can repo.update work??? I thought what works is Repo.update (module, function attribute). repo is an instance of Repo. How can we invoke a function against an instance of something?

|> Ecto.Multi.run(
  :name,
  fn repo, _changes ->
    {:ok, image} = Images.get(image_id)
    repo.update(
      Image.processed_image_changeset(image)
    )
  end)
)

repo is a variable bound to a module, it isn’t an “instance” of anything. There are no “instances” of modules in Elixir, modules are collections of functions.

repo = YourApplication.Repo
repo.insert(changeset)

you can assign a module to a variable and then call that module’s functions using the variable.

1 Like

I see so i guess one could just do

|> Ecto.Multi.run(
  :name,
  fn _repo, _changes ->
    {:ok, image} = Images.get(image_id)
    Repo.update(
      Image.processed_image_changeset(image)
    )
  end)
)

with the same effect. Then it makes me wonder why the api was designed to expected a function of fn repo, changes. Feel like repo is useless

Right, if your repository is static :slight_smile:

but you could also have dynamic repositories: Replicas and dynamic repositories — Ecto v3.8.4

Imagine you’re selecting your repo dynamically from a list of replicas and then executing your multi on it:

MyApp.Repo.replica().transaction(multi)

Then it’s handy to receive the repo as the first argument of the run callback. Otherwise you wouldn’t know which repository you have to work with.

4 Likes

Right that makes a lot of sense. Thank you