2016-07-06 43 views
7

Chcę wyświetlać dane z mojego DB przez Ecto w niestandardowym poleceniu mieszania. Jak mogę uzyskać repozytorium Epoo w moim zadaniu (lub uruchomić je)?Jak uzyskać dane z Ecto w zadaniu niestandardowego miksu

Próbowałem coś takiego, ale to nie działa:

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 

To da mi następujące dane wyjściowe, kiedy uruchomić mieszać 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 

Każdy pomysł lub inny sposób by rozwiązać ten problem?

Odpowiedz

11

Tu jest rzeczywiście moduł pomocnik Mix.Ecto (https://github.com/elixir-ecto/ecto/blob/master/lib/mix/ecto.ex), który sprawia, że ​​łatwiej napisać mieszać zadania, które używają ekto:

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 

Ten helper zapewnia dostęp do parse_repo/1, ensure_repo/2, ensure_started/1. parse_repo sprawi, że twoje zadanie będzie pasować do innych zadań związanych z miksem ecto, na przykład pozwoli ci przekazać -r, aby określić inne repozytorium.

➤ 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 pilnuje repo działa, której brakowało.

celu uzyskania wskazówek i inspiracji, można spojrzeć na to, jak inne zadania mix ekto są realizowane w https://github.com/elixir-ecto/ecto/tree/master/lib/mix/tasks

+0

dziękuję. Tego właśnie mi brakowało! ! –

+1

Zasób 'ensure_started' został zmieniony z 1 na 2, ponieważ Ecto 2.0. Drugim argumentem jest lista słów kluczowych. Powinniśmy zmienić linię 'ensure_started (repo)' na 'ensure_started (repo, [])'. – Tsutomu

+1

@ Dzięki Tsutomu, zaktualizowałem kod – splatte

2

Trzeba zapewnić repo zostanie uruchomiony przed użyciem

MyApp.Repo.start_link 
0

Znalazłem też inne rozwiązanie podczas pracy z Phoenix. I stworzył nowy plik w priv/repo z:

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 

Potem uruchom go z mix run priv/repo/users.list.exs z mojego korzenia projektu.

5

Jako odpowiedź na odpowiedź Jason Harrelson: konieczne jest również uruchomienie Postgrex i Ecto.

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

MyApp.Repo.start_link 

UPDATE:

Innym podejściem jest użycie zadania mix, aby rozpocząć aplikację:

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