2015-12-17 13 views
9

Per alcuni query in controller di Phoenix, Ci sono due piani per meDevo usare Ecto.Repo in Controller o Model per Elixir Phoenix?

Piano 1:

defmodule Demo.UserController do 
    # ... 
    def index do 
    # This is just for example 
    # The point is Repo in used here 
    Repo.all(User) 
    end 
end 

Piano 2:

defmodule Demo.User do 
    # ... 
    def all do 
    # Put all Repo API and building query logic in Model 
    Repo.all(__MODULE__) 
    end 
end 

preferisco il Piano 2. Poiché nella maggior parte situazioni, posso mettere tutta la logica sul recupero dei dati nel modello.

Ma trovo utilizzo guida ufficiale Plan 1 (docs/model) e di default Phoenix codice alias Repo nel controller al posto del modello (web/web.ex)

Qual è la migliore? E perché?

risposta

16

È necessario mantenere le chiamate di Repo all'interno del controller. Se la tua logica è complicata, dovresti considerare di spostare la logica nel proprio modulo di servizio.

Si dovrebbe trattare il modello come puro (privo di effetti collaterali) in modo che possano agire solo sui dati. Così, per esempio si potrebbe avere:

def alphabetical(query) 
    order_by(query, [u], u.name) 
end 

Ma non si dovrebbe avere:

def alphabetical(query) 
    order_by(query, [u], u.name) 
    |> Repo.all 
end 

Questo perché le query sono puramente i dati, la chiamata a Repo.all ha effetti collaterali (andando fuori al database) in modo appartiene al tuo controller.

+0

Ciao, ho un'altra domanda su questo problema. Se metto chiamate Repo nel controller, come testare il modello? Proprio come il tuo esempio, dovrei usare Repo per inserire alcuni record, poi fare il test (sembra un test di integrazione) o semplicemente testare il risultato di 'order_by'? btw, non ho idea di come testare il risultato di 'order_by'. –

+1

Nella programmazione di Phoenix si consiglia agli sviluppatori di disporre di due file di test nei test/modelli: user_test.exs e user_repo_test.exs. Il primo è possibile testare i changeset e tutto ciò che non richiede il repository. Il vantaggio è che puoi eseguire "async: true" in alto. L'altro richiede il repository e potrebbe essere il posto in cui testare query complesse. Tutto dipende dal tipo di test che si desidera scrivere. –