Как получить данные от Ecto в пользовательской задаче mix

Я хочу отображать данные из моей БД через Ecto в пользовательской задаче mix. Как я могу получить Ecto repo в своей задаче (или запустить ее)?

Я пробовал что-то вроде этого, но это не сработало:

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

это даст мне следующий результат при запуске пользователей mix.список:

** (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

любая идея или другой способ решить эту проблему?

4 ответов


на самом деле есть вспомогательный модуль Mix.Ecto (https://github.com/elixir-ecto/ecto/blob/master/lib/mix/ecto.ex), что облегчает написание задач mix, которые используют 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

этот помощник дает вам доступ к parse_repo/1, ensure_repo/2, ensure_started/1. parse_repo позволит вашей задаче хорошо вписаться в другие задачи Ecto mix, например, это позволит вам пройти-r, чтобы указать другое РЕПО.

➤ 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 убеждается что РЕПО бежит, которое вы были недостающий.

для руководства и вдохновения вы можете посмотреть, как другие задачи Ecto mix реализованы в https://github.com/elixir-ecto/ecto/tree/master/lib/mix/tasks


как дополнение к Jason Harrelsonответ: это также необходимо, чтобы начать Postgrex и Ecto.

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

MyApp.Repo.start_link

обновление:

другой подход-использовать задачу mix для запуска приложения:

Mix.Task.run "app.start", []

вы должны убедиться, что РЕПО запускается до его использования

MyApp.Repo.start_link

Я также нашел другое решение при работе с Phoenix. Я создал новый файл в priv/repo С :

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

затем я запускаю его с mix run priv/repo/users.list.exs из моего корневого каталога проекта.