Protocol Enumerable not implemented for #Ecto.Association.NotLoaded

Hello folks,

I am currently trying to take an object and return some data on it via an endpoint. This object, an account, has many account opportinities and I am running into this error.

protocol Enumerable not implemented for #Ecto.Association.NotLoaded<association :account_opportunities is not loaded> of type Ecto.Association.NotLoaded (a struct). This protocol is implemented for the following type(s): Ecto.Adapters.SQL.Stream, Postgrex.Stream, DBConnection.Stream, DBConnection.PrepareStream, Scrivener.Page, KafkaEx.Stream, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream

This is the method the endpoint hits.

def accounts_by_owner(conn, %{"owner_id" => id, "email" => email}) do
    result = 
      Data.get_account_by_email(email, id)
      |> Enum.map(fn account -> 
        CrmManagerWeb.AccountView.render("account_with_opportunities.json", account: account) end)

    json(conn, %{accounts: result})
  end

I am trying to map it to this json view.

def render("account_with_opportunities.json", %{account: account}) do
    %{
      crm_type: account.crm_type,
      crm_id: account.crm_id,
      match_source: account.match_source,
      opportunities:
        render_many(
          account.account_opportunities,
          CrmManagerWeb.AccountOpportunityView,
          "slim_account_opportunity.json"
        )
    }
    |> Map.merge(account.other_data || %{})
  end

It throws this error when trying to render many. I’m not entirely sure what it going on here. The query that I am running to get these accounts returns something like this…

[       
  %CrmManager.Data.Account{
    __meta__: #Ecto.Schema.Metadata<:loaded, "accounts">,
    account_dsm_ids: #Ecto.Association.NotLoaded<association :account_dsm_ids is not loaded>,
    account_opportunities: #Ecto.Association.NotLoaded<association :account_opportunities is not loaded>,
    account_owner_email: nil,
    contacts: #Ecto.Association.NotLoaded<association :contacts is not loaded>,
    crm_id: "TEST-A",
    crm_type: :sf,
    id: 33,
    inserted_at: ~N[2019-02-06 15:37:16],
    match_source: :integration,
    other_data: %{},
    owner_id: "12345",
    updated_at: ~N[2019-02-06 15:37:16]
  },
  %CrmManager.Data.Account{
    __meta__: #Ecto.Schema.Metadata<:loaded, "accounts">,
    account_dsm_ids: #Ecto.Association.NotLoaded<association :account_dsm_ids is not loaded>,
    account_opportunities: #Ecto.Association.NotLoaded<association :account_opportunities is not loaded>,
    account_owner_email: nil,
    contacts: #Ecto.Association.NotLoaded<association :contacts is not loaded>,
    crm_id: "TEST-B",
    crm_type: :salesforce,
    id: 34,
    inserted_at: ~N[2019-02-06 16:19:21],
    match_source: :integration,
    other_data: %{},
    owner_id: "12345",
    updated_at: ~N[2019-02-06 16:19:21]
  }
]

Any ideas what could be going on here? Perhaps I need to preload the associations?

The exception you are receiving stems from the fact that you aren’t preloading the associated account opportunities in the account.