#Ecto.Association.NotLoaded问题

时间:2017-09-23 17:15:38

标签: elixir phoenix-framework ecto

我有这个模板并且工作正常

Ionic 3

当我写这个测试时,它开始抱怨没有预装的类别:

<h2>Listing videos</h2>

<table class="table">
  <thead>
    <tr>
      <th>User</th>
      <th>Url</th>
      <th>Title</th>
      <th>Description</th>
      <th>Category</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
<%= for video <- @videos do %>
    <tr>
      <td><%= video.user_id %></td>
      <td><%= video.url %></td>
      <td><%= video.title %></td>
      <td><%= video.description %></td>
      <td><%= if category = video.category, do: category.name %></td>

      <td class="text-right">
        <%= link "Show", to: video_path(@conn, :show, video), class: "btn btn-default btn-xs" %>
        <%= link "Edit", to: video_path(@conn, :edit, video), class: "btn btn-default btn-xs" %>
        <%= link "Delete", to: video_path(@conn, :delete, video), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger btn-xs" %>
      </td>
    </tr>
<% end %>
  </tbody>
</table>

<%= link "New video", to: video_path(@conn, :new) %>

错误:

defmodule Rumbl.VideoViewTest do
  use Rumbl.ConnCase, async: true
  import Phoenix.View

  test "renders index.html", %{conn: conn} do
    videos = [%Rumbl.Video{id: "1", title: "dogs"},
              %Rumbl.Video{id: "2", title: "cats"}]
    content = render_to_string(Rumbl.VideoView, "index.html",
                               conn: conn, videos: videos)

    assert String.contains?(content, "Listing videos")
    for video <- videos do
      assert String.contains?(content, video.title)
    end
  end

  test "renders new.html", %{conn: conn} do
    changeset = Rumbl.Video.changeset(%Rumbl.Video{})
    categories = [{"cats", 123}]
    content = render_to_string(Rumbl.VideoView, "new.html",
      conn: conn, changeset: changeset, categories: categories)
    assert String.contains?(content, "New video")
  end
end

为什么抱怨?我在哪里预加载类别?我不明白这个错误,如果视频没有任何类别它不应该崩溃

更新了控制器索引视图代码

...

  1) test renders index.html (Rumbl.VideoViewTest)
     test/views/video_view_test.exs:5
     ** (KeyError) key :name not found in: #Ecto.Association.NotLoaded<association :category is not loaded>
     code: content = render_to_string(Rumbl.VideoView, "index.html",
     stacktrace:
       (rumbl) web/templates/video/index.html.eex:21: anonymous fn/3 in Rumbl.VideoView."index.html"/1
       (elixir) lib/enum.ex:1811: Enum."-reduce/3-lists^foldl/2-0-"/3
       (rumbl) web/templates/video/index.html.eex:15: Rumbl.VideoView."index.html"/1
       (phoenix) lib/phoenix/view.ex:335: Phoenix.View.render_to_iodata/3
       (phoenix) lib/phoenix/view.ex:342: Phoenix.View.render_to_string/3
       test/views/video_view_test.exs:8: (test)

1 个答案:

答案 0 :(得分:1)

是的,您必须在控制器中预加载类别。

在预加载视频之前,你不知道视频是否有任何类别(不是通过询问if video.category)。这是因为没有预加载的video.category会返回#Ecto.Association.NotLoaded<association :category is not loaded>,而不是您预期的nil

对于单一类别,您可以询问if video.category_id,假设视频为belongs_to类别。如果视频没有类别,它会为您nil