chrism2671

chrism2671

How to do many to many relationships with Phoenix Contexts?

I have a newbie question, but I think it’s tangentially relevant to the discussion as it’s not obvious how to do it, even from the Phoenix documentation.

A many-to-many relationship. A user has many chat rooms. A chat room has many users.

In SQL, this requires another table user_room. I would normally create this as a model, and then on my user model, add:
many_to_many :users, User, join_through: "user_rooms"

The question is:

  • In the world of contexts, where do I put user_room, and why?
  • If I’m joining tables in Ecto, is that really separate?

Most Liked

Zesky665

Zesky665

That is done inside the schema files for the models you are trying to link. The context handles mostly controller logic like CRUD, which you will need to update to work with the new relation.

If you’re interested in a example, this is one of the better ones: Elixir learning: Making a unified tagging system with many to many ecto relations

peerreynders

peerreynders

One thing that doesn’t seem to get emphasized enough is that Phoenix Contexts are primarily about cleaning up the controller code and getting domain logic out of the controllers. Compare from

Programming Phoenix
https://media.pragprog.com/titles/phoenix/code/controllers_views_templates/listings/rumbl/web/controllers/user_controller.ex

defmodule Rumbl.UserController do
  use Rumbl.Web, :controller

  def index(conn, _params) do
    users = Repo.all(Rumbl.User) # accessing the Ecto repo directly
    render conn, "index.html", users: users
  end
end

to Programming Phoenix 1.4
https://media.pragprog.com/titles/phoenix14/code/controllers_views_templates/listings/rumbl/lib/rumbl_web/controllers/user_controller.ex

defmodule RumblWeb.UserController do
  use RumblWeb, :controller

  alias Rumbl.Accounts

  def index(conn, _params) do
    users = Accounts.list_users() # here it's up to the Accounts context to figure out where the data comes from
    render(conn, "index.html", users: users)
  end
end

From that perspective it’s OK to start with one context. Once domain logic starts piling up in your first context module you’ll probably have a much better idea how to break out additional contexts.

When it comes to Bounded Contexts you need a lot more domain information and understanding up front in order to make some good decisions. Ideally each bounded context would have data autonomy i.e. it’s own database (separate Ecto repo) so you wouldn’t be using Ecto joins any way.

programming-phoenix-1-4_b2_0 p.73:

Sometimes it may be tricky to determine if two resources belong to the same context or not. In those cases, prefer distinct contexts per resource and refactor later if necessary. Otherwise you can easily end-up with large contexts of loosely related entities. In other words: if you are unsure, you should prefer explicit modules (contexts) between resources.

but

Chris McCord warns about premature extraction - i.e. it’s all about tradeoffs

Also:

Where Next?

Popular in Questions Top

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
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
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
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
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
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
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
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
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
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
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement