caslu

caslu

Hello guys! I’m developing an API only Phoenix project for pet donations, and at the moment i have the following schemas:

  • User schema:
  schema "users" do
    field :name, :string
    field :email, :string
    field :bio, :string
    field :avatar, :string
    field :website, :string
    field :phone, :string
    field :social_links, {:array, :string}
    field :roles, {:array, Ecto.Enum}, values: [:ADOPTER, :DONOR]
    has_many :pets, Announcements.Pet, foreign_key: :owner_id

    timestamps(type: :utc_datetime)
  end
  • Pet schema:
  schema "pets" do
    field :name, :string
    field :size, :decimal
    field :bio, :string
    field :photos, {:array, :string}
    field :age, :integer
    field :gender, Ecto.Enum, values: [:MALE, :FEMALE]
    field :species, Ecto.Enum, values: [:DOG, :CAT]
    field :vaccinated, :boolean, default: false
    field :dewormed, :boolean, default: false
    field :neutered, :boolean, default: false
    field :disability, :boolean, default: false
    field :pedigree, :boolean, default: false
    field :weight, :decimal
    belongs_to :user, Accounts.User, foreign_key: :owner_id
    belongs_to :breed, Announcements.Breed, foreign_key: :breed_id

    timestamps(type: :utc_datetime)
  end
  • and the Breed schema:
  schema "breeds" do
    field :name, :string
    field :temperaments, {:array, :string}
    has_many :pets, Announcements.Pet, foreign_key: :breed_id

    timestamps(type: :utc_datetime)
  end

As you can see, the relations above are pretty simple actually, users can own many pets announces and therefore each pet announcement belongs to a user, each pet belongs to a breed, and this specific breed can own a lot announcements, so another many to one relationship.

The problem is around pets and breeds, when i insert a pet, breed or user everything looks fine, but when i trigger the show action on pets_controller the Jason complains that it’s unable to encode because of NotLoaded Association. I know there's questions similars and i know i could preloadthe breeds association with pets, but the weird fact for me is that Jason does not complain if i don't preload the:userassociation, and when i triggershowaction ofuser_controller` Jason does the encoding pretty well even with not loaded pet associations, so what i want to understand is why this error is happening with only one association.

Showing Posts 1 to 10

cmo

cmo

I think you’ll need to show the code that is loading stuff from the database.

03juan

03juan

This sounds like the same kind of issue I answered in another post recently. Ecto `change/2` preloading associations? - #3 by 03juan

Basically when you build a new struct, the change function replaces NotLoaded with the respective “empty” value, nil for belongs_to and has_one or [] for has_many, specifically for things like forms so you don’t have to do it manually. But when you’re loading an existing record from the db you have to preload the association to replace the NotLoaded struct before you access the data.

Since you mention Jason I assume you’re setting up your own api controller. If you want to send the base struct without having to preload, the you can either @derive {Jason.Encoder, except: [:user, :breed]} above the schema "pets" declaration, which will always strip out those keys when serialising, or manually define your own protocol implementation so you can send the nested user and breed when they’re preloaded or exclude those keys when their values are NotLoaded.

See the defimpl Jason.Encoder example and let us know how it goes.

caslu

caslu OP

Just a regular Repo.get! function is enough to trigger the error

caslu

caslu OP

I’ve tried the derive on pets schema but had not successful at all, Jason still complained about the Not Loaded Association

03juan

03juan

I’m sorry, my code is actually incomplete, you also have to exclude the :__meta__ key or it fails with ** (RuntimeError) cannot encode metadata from the :__meta__ field. However it should have removed the other keys and not complain about NotLoaded.

Please post the code for your derivation and the output from an iex session showing the failure, or how you’re using the struct in your controller.

Can’t help any more than this without it…

Does Repo.get!(Announcements.Pet, pet_id) error in iex?

dimitarvp

dimitarvp

You likely have this somewhere in your controller(s)?

|> json(...)
caslu

caslu OP

It doesn’t because the problem is not with Ecto, just related, the problem is when Jason tries to encode it, at the moment my code snippet of pet schema is just like that:

  @derive {Jason.Encoder, except: [:user, :breed, :__meta__]}
  schema "pets" do
    field :name, :string
    field :size, :decimal
    field :bio, :string
    field :photos, {:array, :string}
    ....

Even with the @derive clause, Jason seems just to ignore, don’t know why, the error remains the same:

(RuntimeError) cannot encode association :breed from PontoCao.Announcements.Pet to JSON because the association was not loaded.

caslu

caslu OP

Don’t mate, the show action of pet_controller looks just like the phoenix auto generate:

def show(conn, %{"id" => id}) do
    pet = Announcements.get_pet!(id)
    render(conn, :show, pet: pet)
end

And the Announcements.get_pet!/1 is just a Repo.get!/1 call

D4no0

D4no0

First of all, ideally you should have a render file where you decide what shape the return will have, it should look the following (this one was generated using mix phx.gen.json Accounts User users name:string age:integer):

defmodule PhoenixTestWeb.UserJSON do
  alias PhoenixTest.Accounts.User

  @doc """
  Renders a list of users.
  """
  def index(%{users: users}) do
    %{data: for(user <- users, do: data(user))}
  end

  @doc """
  Renders a single user.
  """
  def show(%{user: user}) do
    %{data: data(user)}
  end

  defp data(%User{} = user) do
    %{
      id: user.id,
      name: user.name,
      age: user.age
    }
  end
end

There you can dictate what you render, it also decouples your controller from your schema.

As for error you are getting, you cannot render associations that are not preloaded. There are 2 options of doing that:

  1. Using Repo.preload/3: Ecto.Repo — Ecto v3.14.0
  2. Using preload from query: Ecto.Query — Ecto v3.14.0

Otherwise if you don’t need them, don’t render them.

03juan

03juan

Yes it’s because there is a NotLoaded value that you haven’t removed or replaced before Jason tries to encode it.

But this is very weird. What does your heex code look like?

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews