Phoenix 框架:未定义函数 LetsPlan.Event.fetch/2。但是 fetch 函数没有在任何地方记录

Phoenix Framework: undefined function LetsPlan.Event.fetch/2. But the fetch function is not documented anywhere

这是有问题的控制器操作(没有相应的视图,只有默认视图):

  def show(conn, %{"id" => id}) do
    event = Repo.get_by!(Event, slug: id)
    render conn, "show.html", event
  end

Phoenix 失败:

[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 函数未在任何地方记录,我的代码从未调用它!

出现错误,因为您将模型直接传递给视图,并且此函数需要 "assigns" 作为第三个参数。分配应该是一张地图。即使您还没有视图,它也会开始评估布局视图 "app.html":

(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 是动态类型的,当你提供错误的类型时,它有时会导致堆栈深处的神秘错误。在这种情况下,检查库源代码以检查它实际需要什么是很有用的。