2017-09-23 10 views
1

我有這樣的模板,它的正常工作#Ecto.Association.NotLoaded問題

<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) 

爲什麼它會抱怨?我需要在哪裏預加載類別?我不明白的錯誤,如果視頻可是沒有任何類別它不應該崩潰

與控制器索引視圖代碼更新

def index(conn, _params, user) do 
    videos = Repo.all(user_videos(user)) |> Repo.preload(:category) 
    render(conn, "index.html", videos: videos) 
    end 

回答

1

是的,你必須在控制器預加載類。

您不知道視頻在預加載前是否有任何類別(而不是詢問if video.category)。這是因爲沒有預加載的video.category返回的是#Ecto.Association.NotLoaded<association :category is not loaded>,而不是nil

對於單一類別,你可以詢問if video.category_id,假設視頻belongs_to類別。如果視頻沒有分類,它會給你nil

+0

mm那麼像這樣的東西可以工作?​​<%= if video.category_id && category = video.category,do:category.name%>儘管Im有語法問題 – lapinkoira

+0

它可以,但如果視頻具有類別並且未預加載,則它不會。 –

+0

mm我注意到我已經預加載控制器視頻中的類別= Repo.all(user_videos(user))|> Repo.preload(:category),所以我不應該得到錯誤的權利? – lapinkoira