2016-07-06 15 views
7

Ich möchte Daten von meinem DB über Ecto in einer benutzerdefinierten Mischaufgabe anzeigen. Wie kann ich das Ecto Repo in meine Aufgabe bringen (oder starten)?So erhalten Sie Daten von Ecto in einer benutzerdefinierten Mischaufgabe

Ich habe versucht, so etwas wie dieses, aber es hat nicht funktioniert:

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 

Das gibt mir die folgende Ausgabe, wenn ich mischen starten 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 

Jede Idee oder andere Art und Weise um dieses Problem zu lösen?

Antwort

11

Es ist eigentlich ein Helfer-Modul Mix.Ecto (https://github.com/elixir-ecto/ecto/blob/master/lib/mix/ecto.ex), die es einfacher zu schreiben mischen Aufgaben macht, die ecto verwenden:

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 

Mit diesem Hilfsprogramm haben Sie Zugriff auf parse_repo/1, ensure_repo/2, ensure_started/1. parse_repo lassen Sie Ihre Aufgabe gut mit anderen Ecto-Mix-Aufgaben zusammenpassen, zum Beispiel lassen Sie -r ein anderes Repo angeben.

➤ 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 stellt sicher, dass der Repo läuft, die Sie fehlten.

Für Führung und Inspiration kann man sich anschaut, wie andere ecto Mix Aufgaben implementiert werden bei https://github.com/elixir-ecto/ecto/tree/master/lib/mix/tasks

+0

Danke. Das war was ich vermisste! ! –

+1

Der Wert von 'use_started' wurde seit Ecto 2.0 von 1 auf 2 geändert. Das zweite Argument ist eine Keyword-Liste. Wir sollten die Zeile 'sure_started (repo)' in 'secure_started (repo, [])' ändern. – Tsutomu

+1

@Tsutomu danke, ich habe den Code aktualisiert – splatte

2

Sie müssen den Repo, um sicherzustellen, gestartet wird vor der Verwendung es

MyApp.Repo.start_link 
0

Ich fand auch eine andere Lösung, wenn sie mit Phoenix zu arbeiten. Ich habe eine neue Datei in priv/repo mit:

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 

Dann laufe ich es mit mix run priv/repo/users.list.exs von meinem Projekt Wurzel.

5

Als Ergänzung zu Jason Harrelson 's Antwort: Es ist auch notwendig, Postgrex und Ecto zu starten.

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

MyApp.Repo.start_link 

UPDATE:

Ein weiterer Ansatz ist Mix Aufgabe zu bedienende Anwendung zu starten:

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