montogeek
Phx.gen.html belongs_to/has_many error
Hi!
I ran the following command to create a resource:
mix phx.gen.html Main Activity activities name:string datetime_start:datetime datetime_end:datetime category_id:references:categories mood_id:references:moods
After some search I discovered that the inputs for the associations are not created automatically, so I tried to do it, for that I did:
- Edit
activity.exschema and added:
+belongs_to :category, Categories
+belongs_to :mood, Moods
-field :category_id, :id
-field :mood_id, :id
Then I used the Main context functions to retrieve all categories and moods and pass it to the new.html form:
changeset = Main.change_activity(%Activity{})
+categories = Main.list_categories() |> Enum.map(fn c -> {c.name, c.id} end)
+moods = Main.list_moods() |> Enum.map(fn m -> {m.name, m.id} end)
+render(conn, "new.html", changeset: changeset, moods: moods, categories: categories)
+<%= label f, :category %>
+<%= select f, :category, @categories, prompt: "Choose" %>
+<%= error_tag f, :category %>
+
+<%= label f, :mood %>
+<%= select f, :mood, @moods, prompt: "Choose" %>
+<%= error_tag f, :mood %>
But when loading the page in the browser I get this error:
protocol Phoenix.HTML.Safe not implemented for #Ecto.Association.NotLoaded<association :category is not loaded> of type Ecto.Association.NotLoaded (a struct). This protocol is implemented for the following type(s): Decimal, Phoenix.LiveComponent.CID, Phoenix.LiveView.Component, Phoenix.LiveView.Comprehension, Phoenix.LiveView.JS, Phoenix.LiveView.Rendered, Time, Integer, Tuple, List, DateTime, NaiveDateTime, Float, Atom, Phoenix.HTML.Form, BitString, Date
What I am doing wrong?
Thanks!
Marked As Solved
dimitarvp
It is, that’s an implementation details of many ORM / data-mapper libraries. It’s quite fine.
Also Liked
stefanchrobot
That’s how Ecto works. Whenever you add an association, you’ll get both fields. This works nicely with preloads:
post = Repo.get(Post, 123) |> Repo.preload([:author, :topic])
# You can now access the associated data
foo = post.author.name
montogeek
I managed to save it with the correct values after adding category_id and mood_id to the cast function!
I edited the Main get_activity function to preload the relationships:
def get_activity!(id) do
Repo.get!(Activity, id)
+ |> Repo.preload([:category, :mood])
end
After inspecting the object when showing it I get this:
%Main.Activity{
__meta__: #Ecto.Schema.Metadata<:loaded, "activities">,
category: %Flytte.Main.Categories{
__meta__: #Ecto.Schema.Metadata<:loaded, "categories">,
activities: #Ecto.Association.NotLoaded<association :activities is not loaded>,
color: "#000000",
id: 2,
inserted_at: ~N[2022-01-01 19:39:45],
name: "Sleep",
updated_at: ~N[2022-01-01 19:39:45]
},
category_id: 2,
datetime_end: ~N[2017-01-01 00:00:00],
datetime_start: ~N[2017-01-01 00:00:00],
id: 8,
inserted_at: ~N[2022-01-01 22:15:28],
mood: %Flytte.Main.Moods{
__meta__: #Ecto.Schema.Metadata<:loaded, "moods">,
activities: #Ecto.Association.NotLoaded<association :activities is not loaded>,
emoji: ":)",
id: 2,
inserted_at: ~N[2022-01-01 19:43:52],
name: "Fine",
updated_at: ~N[2022-01-01 19:43:52]
},
mood_id: 2,
name: "Test5",
updated_at: ~N[2022-01-01 22:15:28]
}
Please note that there is a category but also category_id, It this ok, to have these 2 values there? Shouldn’t it be only one?
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









