Multiple Ecto Repos in one Phoenix application
Published: 2020-10-31 17:35:40

I recently wanted to use multiple repos in one Phoenix application. I ran into Geoffrey Lessel's [excellent guide](https://geoffreylessel.com/2016/connecting-to-multiple-databases-with-ecto/) from 2016 that worked well.

However, I found it annoying that `mix ecto.reset` didn't accept the option `-r` to specify which Repo to target like the other mix commands (for example, `mix ecto.migrate -r MyApp.MyOtherRepo`). I browsed through the mix folder of Ecto's source code, but I couldn't find where the reset command was defined. At this point I remembered that some mix commands are just shortcuts to existing commands defined in your `mix.exs`. I hadn't defined any, but `mix phx.new` had.

At the bottom of my `mix.exs`, I saw

```elixir
# Aliases are shortcuts or tasks specific to the current project.
# For example, to install project dependencies and perform other setup tasks, run:
#
#     $ mix setup
# See the documentation for `Mix` for more info on aliases.
defp aliases do
    [
        setup: ["deps.get", "ecto.setup", "cmd npm install --prefix assets"],
        "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
        "ecto.reset": ["ecto.drop", "ecto.setup"],
        test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"]
    ]
end
```

To fix the issue, I modified the commands so they also worked on my other Repo.

```elixir
# Aliases are shortcuts or tasks specific to the current project.
# For example, to install project dependencies and perform other setup tasks, run:
#
#     $ mix setup
# See the documentation for `Mix` for more info on aliases.
defp aliases do
    [
        setup: ["deps.get", "ecto.setup", "cmd npm install --prefix assets"],
        "ecto.setup": ["ecto.create", "ecto.create -r Backpackingmap.OsmRepo", "ecto.migrate", "ecto.migrate -r Backpackingmap.OsmRepo", "run priv/repo/seeds.exs"],
        "ecto.reset": ["ecto.drop", "ecto.drop -r Backpackingmap.OsmRepo", "ecto.setup", "ecto.setup -r Backpackingmap.OsmRepo"],
        test: ["ecto.create --quiet", "ecto.create --quiet -r Backpackingmap.OsmRepo", "ecto.migrate --quiet", "ecto migrate --quiet -r Backpackingmap.OsmRepo", "test"]
    ]
end
```

Except the new commands didn't run. It turns out [mix deduplicates commands](https://hexdocs.pm/mix/Mix.html#module-aliases), so we need to change our code to

```elixir
  defp aliases do
    [
      setup: [
        "deps.get",
        "ecto.setup",
        fn _ -> Mix.Task.reenable("ecto.setup") end,
        "ecto.setup -r Backpackingmap.OsmRepo",
        "cmd npm install --prefix assets"
      ],
      "ecto.setup": [
        "ecto.create",
        fn _ -> Mix.Task.reenable("ecto.create") end,
        "ecto.create -r Backpackingmap.OsmRepo",
        "ecto.migrate",
        fn _ -> Mix.Task.reenable("ecto.migrate") end,
        "ecto.migrate -r Backpackingmap.OsmRepo",
        "run priv/repo/seeds.exs"
      ],
      "ecto.reset": [
        "ecto.drop",
        fn _ -> Mix.Task.reenable("ecto.drop") end,
        "ecto.drop -r Backpackingmap.OsmRepo",
        "ecto.setup",
        fn _ -> Mix.Task.reenable("ecto.setup") end,
        "ecto.setup -r Backpackingmap.OsmRepo"
      ],
      test: [
        "ecto.create --quiet",
        fn _ -> Mix.Task.reenable("ecto.create") end,
        "ecto.create --quiet -r Backpackingmap.OsmRepo",
        "ecto.migrate --quiet",
        fn _ -> Mix.Task.reenable("ecto.migrate") end,
        "ecto.migrate --quiet -r Backpackingmap.OsmRepo",
        "test"
      ]
    
```