Hello all!
Yet again, I’ve run across a problem with Ecto: it seems to be my nemesis!
In this instance, I’m trying to build an admin area for a travel blog. The application allows a user to submit Posts
, and Places
. These are in two separate contexts (Content.Post
& Locations.Place
). The desired outcome is that when a user is submitting a Post
they associate a Place
through a Location.Visit
.
In an effort to provide a nice editing experience, I’ve created another context called Admin
which uses an “embedded_schema” for a Admin.Post
model, which combines the required fields into one model.
This is to avoid using Phoenix’s nested forms, and also to leverage Ecto.Multi.
All of the above works correctly for creation of new Posts & Places. However, I can’t seem to use the same model/form to update them.
I’ve written a query to load the data from the various tables and load it back into an %Admin.Post{}
struct, which I pass to the form, along with a changeset. When I try to submit updates, Phoenix tries to use a POST route rather than a PUT or a PATCH. I understand this is because the changeset doesn’t have a :loaded
state because I built it manually (from it’s constituent models), so it infers that this should be a creation, not an update.
I’ve only been able to find examples of inserts with an embedded_schema (use case is usually something like “registration”, which obviously doesn’t require updates). Is something like this possible with “embedded_schemas”?
Now, the real problem here is that I just don’t seem to be able to get my head around associations with Ecto properly. I understand them well enough, and can build them so that they work perfectly well in iex
. I’ve done this for multiple approaches: nested data structures where cast_assoc
is used, a get_or_insert
approach that uses put_assoc
as explained in “What’s new in Ecto”, and another using embedded_schema
and Ecto.Multi
.
Where all of these fall apart for me is when I come to use them through Phoenix. The only approach that I’ve been able to get working is with nested forms and cast_assoc
.
This has been an issue for me in every Elixir/Phoenix project that I’ve started over the last 18 months, with all of them bar one falling by the wayside. No matter how simple I make the problem, as soon as there’s a non-trivial association going on, I hit a wall.
I’ve hunted high and low for advice and guidance on this. Most tutorials or examples are necessarily simple, and don’t really try to solve the same problems I’m encountering. “What’s new in Ecto” has helped me learn a lot about Ecto, but I still haven’t got to a stage where I’m comfortable with it.
The best example I’ve found of the types of associations I’m trying to model is in the Changelog codebase, but from what I can tell, their approach uses nested forms, cast_assoc and a sprinkling of JS to achieve the desired outcome of managing other models (hosts and sponsors in their case) whilst adding an episode. I’m not adverse to this approach at all, but in the spirit of learning and understanding, I’m keen to see what an approach that uses “embedded_schemas” would look like.
Am I just being a bit dim with all this? Given the things I’ve worked on previously, I don’t think I should be struggling with this the way that I am. However, the fact is that I just can’t get my head around it, and almost would prefer to just write plain SQL. That would of course leave me without Ecto’s brilliant integration with Phoenix and assistance with storing & querying data, but at this stage, I don’t know what else I can do/read to understand Ecto properly.
Does anyone know of an example, or a book, or a video course that might help me understand this?
Cheers, Jamie.