2016-04-27 37 views
2

我失去了一些基本的东西与我的凤凰代码药剂地图改变结构周围

这是在我的控制器

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 

在我看来

# 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 

,但我得到通过一个错误,这似乎是因为我的数据已经从%{user: ..., estimates: [...]}变为%{user: %{estimates:[...], user: %{...}}

这是怎么发生的,我该如何预防呢?

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"} 

回答

3

render_one/4功能render_many/4从视图活用的受让人的名称。我在Render many to many relationship JSON in Phoenix Framework

解释所以,当你调用会发生什么:

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

那是render被称为具有下列参数:

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

您可以更改使用as受让人的名称:

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

哪会调用与渲染:

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

你可以匹配这个:

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

另一种选择是:

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

你可以通过调用render,而不是直接使用render_one避免这种使用嵌套在用户结构内的估计的数据结构。也许通过向模式添加虚拟属性。

编辑

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

这使一个很大的区别,但现在我得到'参数错误 (STDLIB):maps.from_list([{1,#Ec。我已经添加了一些代码,我认为我的查询提供了一个列表,并且我可以对该列表进行模式匹配,但是不确定事实上是这种情况 –

+0

看起来你有点偏离轨道,检查我的编辑 – Gazler

+0

感谢!!看起来你有一个错字,因为它最终需要'估计:render_many(估计,__MODULE__,“estimated.json”,作为::估计)}' –

3

这是如何发生的,以及我怎么能阻止它?

这是因为Phoenix.View.render_one将您的分配包裹在视图名称中的关键字中。

From its docs

以下:

render_one user, UserView, "show.html" 

大致等同于:

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

底层用户被传递到视图和模板:user,其被屈折从视图名称。

你应该只调用render/2直接:

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

做了一个很大的区别,但我现在越来越'参数错误 (stdlib):maps.from_list([{1,#Ec ...'。我已经添加了更多的代码。我以为我的查​​询是提供一个列表,我可以模式匹配,但不确定事实如此 –