How to get data from Ecto in a custom mix task

I want to display data from my database through Ecto in a custom mix task. How can I get Ecto relay in my task (or run it)?

I tried something like this, but this did not work:

defmodule Mix.Tasks.Users.List do use Mix.Task use Mix.Config use Ecto.Repo, otp_app: :app @shortdoc "List active users" @moduledoc """ List active users """ def run(_) do import Ecto.Query, only: [from: 1] Mix.shell.info "=== Active users ===" query = from u in "users" sync = all(query) Enum.each(users, fn(s) -> IO.puts(u.name) end) end end 

This will give me the following result when I run mix users.list:

 ** (ArgumentError) repo Mix.Tasks.Users.List is not started, please ensure it is part of your supervision tree lib/ecto/query/planner.ex:64: Ecto.Query.Planner.query_lookup/5 lib/ecto/query/planner.ex:48: Ecto.Query.Planner.query_with_cache/6 lib/ecto/repo/queryable.ex:119: Ecto.Repo.Queryable.execute/5 

Any idea or other way to solve this problem?

+7
elixir phoenix-framework mix
source share
4 answers

Actually there is a Mix.Ecto helper module ( https://github.com/elixir-ecto/ecto/blob/master/lib/mix/ecto.ex ) that simplifies recording mixing tasks using ecto:

 defmodule Mix.Tasks.Users.List do use Mix.Task import Mix.Ecto def run(args) do repos = parse_repo(args) Enum.each repos, fn repo -> Mix.shell.info "=== Active users ===" ensure_repo(repo, args) ensure_started(repo, []) users = repo.all(Ectotask.User) Enum.each(users, fn(s) -> IO.puts(s.name) end) end end end 

This helper gives you access to parse_repo/1 , ensure_repo/2 , ensure_started/1 . parse_repo will allow your task to fit well into other ecto mix tasks, for example, it will allow you to pass -r to specify a different repo.

 ➀ mix users.list === Active users === Adam ➀ mix users.list -r Ectotask.Repo22 === Active users === ** (Mix) could not load Ectotask.Repo22, error: :nofile. Please pass a repo with the -r option. 

ensure_started ensures that the repository is working, which is what you are missing.

For guidance and inspiration, you can see how other ecto mix tasks are implemented at https://github.com/elixir-ecto/ecto/tree/master/lib/mix/tasks

+11
source share

In addition to Jason Harrelson answer: Postgrex and Ecto must also be launched.

 [:postgrex, :ecto] |> Enum.each(&Application.ensure_all_started/1) MyApp.Repo.start_link 

UPDATE:

Another approach is to use the mixing task to launch the application:

 Mix.Task.run "app.start", [] 
+5
source share

You need to ensure that the repo is running before using it.

 MyApp.Repo.start_link 
+2
source share

I also found another solution when working with Phoenix. I created a new file in priv/repo with:

 defmodule Users.List do def run() do Mix.shell.info "=== Active users ===" users = App.Repo.all(App.User) Enum.each(users, fn(s) -> Mix.shell.info("#{s.name}") end) end end Users.List.run 

Then I run it with mix run priv/repo/users.list.exs from my project root.

0
source share

All Articles