2016-04-27 4 views
2

ich etwas Grundsätzliches mit meinem phoenix Code fehltElixir Map-Struktur zu ändern als bestanden um

Dies ist in meinen Controller

def show(conn, %{"id" => id}) do 
    user = Repo.get!(User, id) 

    query = 
     from c in Card, 
      where: c.user_id == 1, 
      select: {c.id, c.inserted_at, c.estimate_name, c.product} 
    estimates = Repo.all(query) 

    render(conn, "show.json", %{user: user, estimates: estimates}) 
    # render(conn, "show.json", user: user) 
    end 

Und meiner Meinung nach

# def render("show.json", %{user: user}) do 
    def render("show.json", %{user: user, estimates: estimates}) do 
    %{data: render_one(%{user: user, estimates: estimates}, Api.UserView, "user.json") } 
    # %{data: render_one(user, Api.UserView, "user.json")} 

    # ** New code since original post ** 
    # %{data: render("user.json", %{user: user, estimates: estimates})} 
    end 

    def render("user.json", %{user: user, estimates: estimates}) do 
    # def render("user.json", %{user: user}) do 
    %{id: user.id, 
     firstname: user.firstname, 
     lastname: user.lastname, 
     email: user.email, 
     customerId: user.customerId, 
     estimates: render("estimates.json", estimates)} # **Line with last error** 
    end 

    def render("estimates.json", [head | _estimates]) do 
    # Enum.map(estimates, fn estimate -> render(mapper estimate, MosaicApi.UserView, "summaryEstimate.json") } end) 
    # render(mapper(head), MosaicApi.UserView, "summaryEstimate.json") 
    render("summaryEstimate.json", mapper(head)) 

    end 

    # ** I'm fear I have added unnecessary complexity here ** 
    def mapper({id, date, name, product}) do 
     %{id: id, 
     creation_date: date, 
     estimate_name: name, 
     product: product} 
    end 

    def render("summaryEstimate.json", estimate) do 
    %{id: estimate.id, 
     estimate_name: estimate.estimate_name, 
     product: estimate.product} 
    end 

Aber ich ein Fehler, der zu sein scheint, weil meine Daten von %{user: ..., estimates: [...]} zu %{user: %{estimates:[...], user: %{...}} gemorpht worden sind.

Wie ist das passiert und wie kann ich das verhindern?

Could not render "user.json" for MosaicApi.UserView, please define a matching clause for render/2 or define a template at "web/templates/user". No templates were compiled for this module. 

Assigns: 

%{user: %{estimates: [{1, #Ecto.DateTime<2016-04-26T12:01:34Z>, "cards for annabelle", "Business Cards"}, ...], user: %Api.User{__meta__: #Ecto.Schema.Metadata<:loaded>, customerId: "CUST", email: "[email protected]", firstname: "fname 1", id: 1, inserted_at: #Ecto.DateTime<2016-04-26T11:46:21Z>, jobs: #Ecto.Association.NotLoaded<association :jobs is not loaded>, lastname: "lname 1", updated_at: #Ecto.DateTime<2016-04-26T11:46:21Z>}}, view_module: Api.UserView, view_template: "user.json"} 

Antwort

3

Die render_one/4 und render_many/4 Funktionen inflect den Abtretungsempfänger Namen aus der Ansicht. Ich erkläre dies in Render many to many relationship JSON in Phoenix Framework

Also, was passiert, wenn Sie anrufen:

render_one(%{user: user, estimates: estimates}, Api.UserView, "user.json") 

Ist das render mit den folgenden Argumenten aufgerufen:

render("user.json", %{user: %{user: %{...}, estimates: [...]}) 

Sie können den Namen des Abtretungs as mit ändern:

render_one(%{user: user, estimates: estimates}, Api.UserView, "user.json", as: :data) 

Wer wird Anruf machen mit:

render("user.json", %{data: %{user: %{...}, estimates: [...]}) 

Sie können dieses Spiel mit:

def render("user.json", %{data: %{user: user, estimates: estimates}}) do 

Sie können dies vermeiden, indem render direkt anstatt mit render_one Aufruf:

render("user.json", %{user: user, estimates: estimates}) 

Eine weitere Option ist eine Datenstruktur verwenden, die die Schätzungen innerhalb der Benutzerstruktur nistet. Vielleicht, indem Sie Ihrem Schema ein virtuelles Attribut hinzufügen.

EDIT

def render("show.json", %{user: user, estimates: estimates}) do 
    %{data: render("user.json", %{user: user, estimates: estimates})} 
    end 

    def render("user.json", %{user: user, estimates: estimates}) do 
    %{id: user.id, 
     ... 
     estimates: render_many(estimates, __MODULE__, "estimates.json", estimates. as: estimate)} 
    end 

    def render("estimates.json", %{estimate: {id, _date, name, product}}) do 
    %{id: id, 
     estimate_name: name, 
     product: product} 
    end 
+0

die einen großen Unterschied gemacht, aber ich bin jetzt immer 'Argument Fehler (stdlib): maps.from_list ([{1, #EC. "Ich habe etwas mehr Code hinzugefügt. Ich dachte, dass meine Abfrage eine Liste liefert und dass ich Muster dafür abgleichen könnte, aber ich bin mir nicht sicher, dass das in der Tat der Fall ist. –

+0

Sieht so aus, als ob du ein bisschen abgehört hast mein redigieren. – Gazler

+0

DANK !! Sieht aus, als ob Sie einen Tippfehler hatten, da er schließlich 'Schätzungen benötigt: render_many (Schätzungen, __MODULE__," schätzt.json ", wie:: Schätzung)}' –

3

Wie das geschehen war, und wie kann ich das verhindern?

Das liegt daran, dass Phoenix.View.render_one Ihre Zuordnungen in einem vom Namen der Ansicht eingeblendeten Schlüssel eingeschlossen hat.

From its docs:

Die folgende:

render_one user, UserView, "show.html" 

entspricht in etwa:

if user != nil do 
    render(UserView, "show.html", user: user) 
end 

Die zugrunde liegende Benutzer als :user zur Ansicht und Template übergeben, die flektiert wird aus dem Namen der Ansicht.

Sie sollten render/2 nur direkt anrufen:

def render("show.json", %{user: user, estimates: estimates}) do 
    %{data: render("user.json", %{user: user, estimates: estimates}} 
end 
+0

That hat einen großen Unterschied gemacht, aber ich bekomme jetzt den Argumentfehler (stdlib): maps.from_list ([{1, #Ec ... '. Ich habe etwas mehr Code hinzugefügt. Ich dachte, dass meine Abfrage eine Liste liefert und dass ich eine Mustererkennung dagegen durchführen könnte, aber ich bin mir nicht sicher, dass das tatsächlich der Fall ist –

Verwandte Themen