tomekowal

tomekowal

Modelling application core with relational entities

I’ve recently finished Designing Elixir Systems with OTP. It is an excellent book, and I highly recommend reading it!

Modelling the logic with pure data structures without using the DB is central to the architecture. In many cases, the core/entities have a relational structure. There is an excellent talk about it by Richard Feldman (the example is in Elm, but the same rules apply).

The problem is many to many relationships. An example from the above talk a student can attend many courses and courses have many students. In such situations, Richard recommended using dictionary (map in Elixir) id => %Student{}

That seems like a pretty clean idea, but I am not sure what to do with new records. Let’s say I want to add a new student to the course. I should generate a new id for that record. However, I should decouple the model from the DB, so I shouldn’t use DB id. But what should I use then? Other ids might be integers from the DB, and I don’t want to clash.

My end goal is a function like save(old_model, new_model) that checks what changes need saving and performs the writes.

I have a couple of ideas, but neither is very compelling.

Idea 1:
Using something like {:db, id} for stuff read from the DB and {:new, id} for new stuff. That makes the save function trivial. The downside is that I am leaking persistence details to the model/core.

Idea 2:
Introduce ids that are unrelated to DB. E.g. a student id might be a string "student-1". That would be unrelated to the DB id. When reading a particular set of courses, I would need to translate student.id: 237 to "student-1", student.id: 250 to `“student-2” and so on. That should work, but I need to keep the translations dictionary somewhere in case I need to update the student.

Do you have any other ideas for persistence? Or maybe an idea of using a map is not a good one, and I should the relationships differently?

Marked As Solved

JEG2

JEG2

Author of Designing Elixir Systems with OTP

My instinct is to favor ID’s unrelated to the database. It might be that you could get by with something as simple as :erlang.unique_integer/0, but my first choice would probably be to use UUID’s.

PostgreSQL supports using UUID’s as the primary key for a record. You can generate a UUID in your application and save it with the other fields. Put another way, you don’t have to have the database auto-assign the primary key (though it certainly will do that when desirable). So I don’t think any additional mapping would be required, if I’ve understood the constraints correctly.

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
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
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
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
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
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36128 110
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement