2015-12-17 5 views
9

Für einige Abfrage in der Steuerung von Phoenix, sind da zwei Pläne für michSoll ich Ecto.Repo in Controller oder Model für Elixir Phoenix verwenden?

Plan 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 

Plan 2:

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

ich den Plan bevorzugen 2. Da in den meisten Situationen, kann ich alle Logik zum Abrufen von Daten in Model setzen.

Aber ich offiziellen Guide Verwendung Plan 1 (docs/model) und Phoenix Standardcode alias Repo in-Controller anstelle von Modell zu finden (web/web.ex)

Welches ist besser? Und warum?

Antwort

16

Sie sollten Ihre Repo-Anrufe in Ihrem Controller behalten. Wenn Ihre Logik kompliziert ist, sollten Sie die Logik in ein eigenes Servicemodul verlagern.

Sie sollten Ihre Modellfunktionen als rein (frei von Nebenwirkungen) behandeln, so dass sie nur auf Daten reagieren sollten. So zum Beispiel könnten Sie haben:

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

Aber Sie sollten nicht haben:

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

Dies liegt daran, Abfragen rein Daten sind, hat der Aufruf von Repo.all Nebenwirkungen (abgehend zur Datenbank), so Es gehört in Ihren Controller.

+0

Hallo, ich habe eine andere Frage zu diesem Problem. Wenn ich Repo-Anrufe in den Controller setze, wie kann ich das Modell testen? Wie in Ihrem Beispiel sollte ich Repo verwenden, um einige Datensätze einzufügen, dann den Test durchführen (es scheint wie ein Integrationstest zu sein) oder einfach das Ergebnis von "order_by" testen? Übrigens, ich habe keine Ahnung, wie ich das Ergebnis von 'order_by' testen soll. –

+1

In Programming Phoenix empfehlen wir Entwicklern, zwei Testdateien in test/models zu haben: user_test.exs und user_repo_test.exs. Mit der ersten können Sie Changesets und alles, was das Repository nicht benötigt, testen. Der Vorteil ist, dass Sie mit "async: true" oben laufen können. Der andere erfordert das Repository und es könnte der Ort sein, an dem Sie komplexe Abfragen testen können. Alles hängt davon ab, welche Art von Test Sie schreiben möchten. –