A full featured Elixir/Ecto seeding solution providing means for dev and prod seeding.
Add phil_columns to your list of dependencies in mix.exs
:
def deps do
[{:phil_columns, "~> 0.1.0"}]
end
Ensure phil_columns is started before your application:
def application do
[applications: [:phil_columns]]
end
Create a Seed
module for you application:
# lib/my_app/seed.ex
defmodule MyApp.Seed do
defmacro __using__(_opts) do
quote do
use PhilColumns.Seed
# shared code here ...
end
end
end
If you need to ensure applications are started before seeding, configure them like this:
config :phil_columns,
ensure_all_started: ~w(timex)a
Use the generator to create a seed.
$ mix phil_columns.gen.seed add_things
The generator puts a seed file in place. Add your seeding logic to the up/1
and/or down/1
functions using any valid Elixir/Ecto code.
# priv/repo/seeds/20160624153032_add_things.exs
defmodule MyApp.Repo.Seeds.AddThings do
use MyApp.Seed
def up(_repo) do
# seeding logic ...
end
end
Execute the seed(s).
$ mix phil_columns.seed
The simplest usage of the seed command defaults the environment to dev
and the version to all
.
$ mix phil_columns.seed
The env can be overridden by providing a switch. The env is used to select only seeds that have been specified for the specified env.
$ mix phil_columns.seed --env=prod
$ mix phil_columns.seed -e prod
Tags and environments can be applied to seeds and filtered in command usage. The seed generator adds the dev
environment by default and no tags. This feature enables efficiency and adaptability in development seeding and
the possibility to use PhilColumns seeding in production (see Production Seeding section below).
Specifying environment(s) for a seed is accomplished with the envs function.
defmodule MyApp.Repo.Seeds.AddThings do
use MyApp.Seed
envs [:dev, :prod]
# ...
end
To change the environment use the env switch. When not specified the env defaults to dev
.
$ mix phil_columns.seed -e prod
Similary, applying tag(s) is accomplished using the tags function.
defmodule MyApp.Repo.Seeds.AddThings do
use MyApp.Seed
envs [:dev, :prod]
tags [:some_tag]
# ...
end
To change the tag(s) provide them after the command command line.
$ mix phil_columns.seed --tags=users,settings,etc
$ mix phil_columns.seed -t users,settings,etc
Systems often have system level data that must be seeded when bootstraping a system or as new features are rolled out. Some examples are settings, configurations, roles, licenses, etc.
PhilColumns provides the ability to apply these system data seedings and commit them with features, analgous to an Ecto migration. Committing seed data with features or bug fixes communicates the intention of the data more clearly than any other strategy can.
Create a module specifically for dealing with seeding in production.
defmodule MyApp.Deployment.Seeder do
import Mix.Ecto
import Mix.PhilColumns
def seed(opts, seeder \\ &PhilColumns.Seeder.run/4) do
repos = parse_repo(opts)
|> List.wrap
# set env with current_env/0 overwriting provided arg
opts = Keyword.put( opts, :env, current_env )
opts =
if opts[:to] || opts[:step] || opts[:all],
do: opts,
else: Keyword.put(opts, :all, true)
opts =
if opts[:log],
do: opts,
else: Keyword.put(opts, :log, :info)
opts =
if opts[:quiet],
do: Keyword.put(opts, :log, false),
else: opts
Enum.each(repos, fn repo ->
exec_task(repo, opts, fn ->
seeder.(repo, seeds_path(repo), :up, opts)
end)
end)
end
defp current_env do
# implement this
# warning: do not use Mix.env if you are doing an erlang release
end
end
Use the module in the production app's remote console.
MyApp.Deployment.Seeder.seed(tags: ~w(things stuff)a)