defmodule Ecto.AutoMigrator do @callback migrate :: :ok @callback rollback(atom, any) :: {:ok, any, any} @callback load_app :: :ok | {:error, any} @callback repos :: list(atom()) @callback run_migrations? :: boolean defmacro __using__(_opts) do quote do @behaviour Ecto.AutoMigrator if Module.get_attribute(__MODULE__, :doc) == nil do @doc """ Automatic migrations module which can be added to the supervision tree """ end @app Mix.Project.config()[:app] use GenServer def start_link(args) do GenServer.start_link(__MODULE__, args, []) end @impl true @spec init(any) :: :ignore def init(_args) do migrate() :ignore end def migrate() do if run_migrations?() do load_app() run_all_migrations(repos) end :ok end def run_all_migrations(repos) do for repo <- repos do {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true)) end end def rollback(repo, version) do load_app() {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version)) end def load_app() do Application.load(@app) end def repos() do Application.fetch_env!(@app, :ecto_repos) end def run_migrations?() do case Application.fetch_env(@app, :run_migrations) do {:ok, val} -> !!val :error -> false end end defoverridable Ecto.AutoMigrator end end end