defmodule Mix.Tasks.Ecto.Gen.Repo do
use Mix.Task
import Mix.Ecto
import Mix.Generator
@shortdoc "Generates a new repository"
@switches [
repo: [:string, :keep],
]
@aliases [
r: :repo,
]
@moduledoc """
Generates a new repository.
The repository will be placed in the `lib` directory.
## Examples
$ mix ecto.gen.repo -r Custom.Repo
This generator will automatically open the config/config.exs
after generation if you have `ECTO_EDITOR` set in your environment
variable.
## Command line options
* `-r`, `--repo` - the repo to generate
"""
@impl true
def run(args) do
no_umbrella!("ecto.gen.repo")
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
repo =
case Keyword.get_values(opts, :repo) do
[] -> Mix.raise "ecto.gen.repo expects the repository to be given as -r MyApp.Repo"
[repo] -> Module.concat([repo])
[_ | _] -> Mix.raise "ecto.gen.repo expects a single repository to be given"
end
config = Mix.Project.config()
underscored = Macro.underscore(inspect(repo))
base = Path.basename(underscored)
file = Path.join("lib", underscored) <> ".ex"
app = config[:app] || :YOUR_APP_NAME
opts = [mod: repo, app: app, base: base]
create_directory Path.dirname(file)
create_file file, repo_template(opts)
config_path = config[:config_path] || "config/config.exs"
case File.read(config_path) do
{:ok, contents} ->
check = String.contains?(contents, "import Config")
config_first_line = get_first_config_line(check) <> "\n"
new_contents = config_first_line <> "\n" <> config_template(opts)
Mix.shell().info [:green, "* updating ", :reset, config_path]
File.write! config_path, String.replace(contents, config_first_line, new_contents)
{:error, _} ->
create_file config_path, "import Config\n\n" <> config_template(opts)
end
open?(config_path, 3)
Mix.shell().info """
Don't forget to add your new repo to your supervision tree
(typically in lib/#{app}/application.ex):
def start(_type, _args) do
children = [
#{inspect repo},
]
And to add it to the list of Ecto repositories in your
configuration files (so Ecto tasks work as expected):
config #{inspect app},
ecto_repos: [#{inspect repo}]
"""
end
defp get_first_config_line(true), do: "import Config"
defp get_first_config_line(false), do: "use Mix.Config"
embed_template :repo, """
defmodule <%= inspect @mod %> do
use Ecto.Repo,
otp_app: <%= inspect @app %>,
adapter: Ecto.Adapters.Postgres
end
"""
embed_template :config, """
config <%= inspect @app %>, <%= inspect @mod %>,
database: "<%= @app %>_<%= @base %>",
username: "user",
password: "pass",
hostname: "localhost"
"""
end