这是有问题的控制器操作(没有相应的视图,只是默认视图):
def show(conn, %{"id" => id}) do
event = Repo.get_by!(Event, slug: id)
render conn, "show.html", event
end
菲尼克斯失败了:
[error] #PID<0.633.0> running LetsPlan.Endpoint terminated
Server: localhost:4000 (http)
Request: GET /events/Evv_YCX71c
** (exit) an exception was raised:
** (UndefinedFunctionError) undefined function LetsPlan.Event.fetch/2
(lets_plan) LetsPlan.Event.fetch(%{__meta__: #Ecto.Schema.Metadata<:loaded>, __struct__: LetsPlan.Event, conn: [...snip...] :conn)
(phoenix_html) lib/phoenix_html/engine.ex:92: Phoenix.HTML.Engine.fetch_assign/2
(lets_plan) web/templates/layout/app.html.eex:11: LetsPlan.LayoutView."app.html"/1
(phoenix) lib/phoenix/view.ex:344: Phoenix.View.render_to_iodata/3
(phoenix) lib/phoenix/controller.ex:633: Phoenix.Controller.do_render/4
(lets_plan) web/controllers/event_controller.ex:1: LetsPlan.EventController.action/2
(lets_plan) web/controllers/event_controller.ex:1: LetsPlan.EventController.phoenix_controller_pipeline/2
(lets_plan) lib/phoenix/router.ex:261: LetsPlan.Router.dispatch/2
(lets_plan) web/router.ex:1: LetsPlan.Router.do_call/2
(lets_plan) lib/lets_plan/endpoint.ex:1: LetsPlan.Endpoint.phoenix_pipeline/1
(lets_plan) lib/plug/debugger.ex:93: LetsPlan.Endpoint."call (overridable 3)"/2
(lets_plan) lib/phoenix/endpoint/render_errors.ex:34: LetsPlan.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
此fetch/2
函数未在任何地方记录,我的代码从不调用它!
答案 0 :(得分:6)
错误显示,因为您将模型直接传递给视图,此函数需要&#34;分配&#34;作为第三个论点。分配应该是一张地图。即使您还没有查看视图,它也会开始评估布局视图&#34; app.html&#34;:
(lets_plan) web/templates/layout/app.html.eex:11: LetsPlan.LayoutView."app.html"/1
布局视图也使用此分配to check for some fields。
最后,你试图在你传递的内容上调用Dict.fetch
,但它失败了,因为它不是带有分配的地图。试试这个:
render conn, "show.html", event: event
它生成一个键:event
,其值为您的模型。现在,您可能会收到不同的错误,提示您为控制器实现视图。
Elixir是动态类型的,当你提供错误的类型时,它有时会在堆栈深处产生神秘错误。在这种情况下,检查库源代码以检查它实际期望的内容是很有用的。