coen.bakker

coen.bakker

How to add fields of associated schema to fields of parent schema when querying with Ecto?

Context
I have several different types of books that are stored in my database. All books have some properties in common, but all book types have their own unique properties as well. Currently, I have a schema for the shared properties of books (books) and one for the non-shared properties of each type of book (type_a_books, type_b_books, etc).

  schema "books" do
    field :title, :string
    ...
    field :type, :string # "TypeABook", "TypeBBook", etc.

    has_many :publications, Publication
    many_to_many :authors, Author, join_through: "authors_books"

    has_one :type_a_book, TypeABook
    has_one :type_b_book, TypeBBook

    timestamps()
  end
  schema "type_a_books" do
    field :story, :string
    field :pictures, {:array, :string}
    belongs_to :book, Book
  end
  schema "type_b_books" do
    field :paths, {:array, :string}
    field :pictures, {:array, :string}
    field :videos, {:array, :string}
    belongs_to :book, Book
  end

I setup this model recently but I am now faced with the fact that I do not have a sufficient understanding of how to perform the needed queries. I have read the documentation of Ecto.Query, Ecto.Repo and Ecto.Schema, and learnt from several other sources.

Problem
I have not been able to figure out how to get the following data back from the database (N.B. the fields of TypeABook are joined to the fields of Book).

%{
  id: "qwerty",
  title: "A Purple Sky over Tokyo",
  ...
  type: "type_a_book",
  publications: [ #App.Publications.Publication<...> ],
  authors: [ #App.Authors.Author<...> ],
  story: "hello",
  pictures: ["url", "url", "url"],
  inserted_at: ~U[2023-02-20 13:06:54Z],
  updated_at: ~U[2023-02-20 13:06:54Z]
}

The closest I got to this result is a simple query = from d in Draft, preload: [:authors, :publications, :type_a_book]. This, however, does not add the fields of TypeABook to the fields of Book. I have also tried to use join in assoc() and join in TypeABook, but I could never get it to work fully.

Feel free to also comment on my model or the general approach I am taking.

Most Liked

milangupta

milangupta

Here is one approach that might work ?

And a previous forum post/pointer from @LostKobrakai - Data mapping and validation — Ecto v3.14.0

LostKobrakai

LostKobrakai

If your read and write side look rather different you can also go with different schemas fror them. Noone requires you do use the same ones.

milangupta

milangupta

Glad it was helpful. It is a learning journey. I’m on my 3rd refactoring / re-design. What I love about the stack is that it is easy for a newbie to create something and then as you learn, you can really create some elegant stuff.

Your choices will really depend on the complexity of your application. There is still more to do with Ecto, but for simple/medium complexity stuff, it is great ! An example where I am still learning .. in designing the model with assocs (has_many/belongs_to etc.), the stuff that I still have to test thoroughly is around when a record is deleted (and the behavior of cascading deletes), specifically when a value is NULL. Postgres15’s addition of NULL not unique was a very very needed enhancement that was previously causing me a lot of workarounds etc.

Hope this helps ..

Where Next?

Popular in Questions Top

WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
yawaramin
In the Dialyzer docs ( dialyzer — OTP 29.0.2 (dialyzer 6.0.1) ), there is a way to turn off a specific warning for a function: -dialyzer...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

We're in Beta

About us Mission Statement