Reputation: 1396
If you need access to DB for you mix task - you needed to start your ecto repo manually. While we worked with ecto 2 we had ensure_started
function.
So custom CLI task with ecto 2 looks like
defmodule App.Task do
use Mix.Task
import Mix.Ecto
def run(args) do
repos = parse_repo(args)
Enum.each repos, fn repo ->
ensure_repo(repo, args)
ensure_started(repo, []) # was deleted from ecto 3
ensure_started
has been deleted from ecto 3. I tried a few approaches but they didn't work for me. Does anybody know a workaround for ecto 3?
Updated
as @starbelly mentioned ensure_started
has migrated to Mix.EctoSQL
so we need to add extra import Mix.EctoSQL
to make it work
defmodule App.Cli.Task do
import Mix.Ecto
import Mix.EctoSQL
def start_ecto do
repos = parse_repo([])
Enum.each(repos, fn repo ->
ensure_repo(repo, [])
{:ok, _pid, _apps} = ensure_started(repo, [])
end)
end
end
Upvotes: 4
Views: 2209
Reputation: 21
For Ecto 3.x use Repo.start_link()
or Mix.Task.run('app.start')
This question/answer might help. How to get data from Ecto in a custom mix task
Upvotes: 1
Reputation: 179
As Dennis pointed out Mix.EctoSQL.ensure_started/2
is a private function since ecto_sql 3.1.2, so we can't use it anymore.
Assuming you have an OTP application defined, which this mix task is part of, what you could do is
defmodule Mix.Tasks.Friends.Hello do
use Mix.Task
def run(args) do
{:ok, _started} = Application.ensure_all_started(:your_otp_app_name)
repos = parse_repo(args)
Enum.each(repos, fn repo ->
repo.all(Friends.Person)
end)
end
end
Essentially start the whole OTP application, so that all the dependencies (including the repos) would be started as well.
Upvotes: 2
Reputation: 96
None of these approaches will work anymore in the latest version of ecto_sql (3.1.2) because Mix.EctoSQL.ensure_started/2
was a private function, not meant for use outside of Ecto.
As per Jose, the correct approach is to use
Mix.Task.run("app.start")
So the example @starbelly shared would be modified to be
defmodule Mix.Tasks.Friends.Hello do
use Mix.Task
def run(args) do
Mix.Task.run("app.start")
repos = parse_repo(args)
Enum.each(repos, fn repo ->
repo.all(Friends.Person)
end)
end
end
The big drawback to this approach is it will start your entire application, including any background processes you have. As a result, you may need to modify your application.ex
file to not start those if started by a mix task.
Upvotes: 3
Reputation: 254
The function you're trying to import and call has been moved into ecto_sql. You should import Mix.EctoSQL
for ensure_started/2
Example:
defmodule Mix.Tasks.Friends.Hello do
use Mix.Task
import Mix.Ecto
import Mix.EctoSQL
def run(args) do
repos = parse_repo(args)
Enum.each(repos, fn repo ->
ensure_repo(repo, args)
{:ok, _pid, _apps} = ensure_started(repo, [])
Friends.Repo.all(Friends.Person)
end)
end
end
Upvotes: 3