2016-07-06 24 views
7

Desidero visualizzare i dati dal mio DB tramite Ecto in un'attività di missaggio personalizzata. Come posso ottenere il repository Ecto nel mio compito (o avviarlo)?Come ottenere dati da Ecto in un'attività di mix personalizzato

Ho provato qualcosa di simile, ma non ha funzionato:

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 

Questo mi darà il seguente output quando lancio mescolare 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 

qualsiasi idea o altro modo risolvere questo problema?

risposta

11

v'è in realtà un modulo helper Mix.Ecto (https://github.com/elixir-ecto/ecto/blob/master/lib/mix/ecto.ex), che rende più facile scrivere mescolare attività che utilizzano 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 

Questo helper consente di accedere a parse_repo/1, ensure_repo/2, ensure_started/1. parse_repo consentirà al tuo compito di adattarsi bene ad altre attività di ecto mix, ad esempio ti consentirà di passare -r per specificare un repository diverso.

➤ 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 si assicura il repo è in esecuzione, che mancavano.

Per guida e di ispirazione, si può guardare come gli altri compiti mix Ecto vengono attuati a https://github.com/elixir-ecto/ecto/tree/master/lib/mix/tasks

+0

Grazie. Questo era quello che mi mancava! ! –

+1

L'arità di 'ensure_started' è stata modificata da 1 a 2 da Ecto 2.0. Il secondo argomento è un elenco di parole chiave. Dovremmo cambiare la riga 'ensure_started (repo)' a 'ensure_started (repo, [])'. – Tsutomu

+1

@Tsutomu grazie, ho aggiornato il codice – splatte

2

È necessario garantire il repo viene avviata prima di usarlo

MyApp.Repo.start_link 
0

ho anche trovato un'altra soluzione quando si lavora con Phoenix. Ho creato un nuovo file in priv/repo con:

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 

Poi lo eseguo con mix run priv/repo/users.list.exs dalla mia radice del progetto.

5

Come aggiunta alla risposta Jason Harrelson: è anche necessario avviare Postgrex e Ecto.

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

MyApp.Repo.start_link 

UPDATE:

Un altro approccio è quello di utilizzare compito mix per avviare l'applicazione:

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