Context / for request state equivalent

Hi I’m an absolute beginner trying to understand how to achieve the same thing I do with object oriented frameworks.
I can’t understand which is the recommended way to load some data at the start of the request that I can use later in my code without re-elaborating it every time. For example the authenticated user. I load it at the begin of the request, place it in a global store(aka context) and I can access it wherever I want since it is global.

Do I have to pass it using parameters? I don’t like the thing of polluting functions with it.
What does phoenix|elixir recommend?

I think what you want to understand is the conn struct provided by Plug, which Phoenix builds atop. Plugs and plug pipelines can be used in your router to do things like authenticate a user and store that user in the conn struct so that once you resolve a particular controller/action you can access it.

However, you are expected to pass that sort of thing into functions lower-level in your business logic (Phoenix calls them “contexts”) where appropriate.

2 Likes

Thanks for the answer. Yeah I was looking for something like that.
But what if in my Phoenix contexts I use the authenticated user a lot? There would be a lot of functions that includes it. Isn’t it common to use some memoization strategy or a way to store it globally and access from my functions?

Sorry if I insist but i find it annoying at first

I would offer to you the argument that is is not “pollution” for a function to accept a user parameter if it depends upon that user to perform its … function properly. That is called functional programming.

There are ways around it, but no, they are not common. What’s common is to have pure functions that take in all the params they need to achieve their function. Those are really easy to write tests for.

3 Likes

Remember there are no objects, and FP does not share the same design patterns.

FP is about having pure functions. Everything is about (pure) composable functions…

1 Like

I probably misphrased it. I meant: I’m doing this thing in oop, is it a thing in elixir or should I do something else?
I’m good with FP principles but maybe I’ve been bad educated by frameworks like React. One way for React to"solve" props passing between sub-components is the Context. In fact React passes the context as a parameter to the component but it allows somehow to get data back from it with it’s utilities. So it still follow the FP rules but has this implicit context passed to components. This way you don’t have the same props passed down to a lot of components. I thought this was a common pattern for FP but looks like it is not

1 Like

The context of a request is the conn structure.

There is no equivalent to React Context… but You have many ways to store shareable data, for example, GenServer, Agent, or ETS table.

BTW I have been using Phoenix with React and I find it an excellent combo. Mostly because it is possible to have 2 data stores, one on the frontend, and one on the server (a GenServer storing shared data for a multiplayer board game)… keeping them sync with channels.

Ok that’s good to know. I guess I need to investigate GenServer, Agent and ETS use cases more. Thanks for your time!

So I was navigating phoenix docs and I saw that whenever you make a query you can use.

Repo.all(...my expresssion...)

Where is the connection here? I don’t think it creates a connection every time I make a query doesn’t it?
Am I missing something?
Is there some state stored under the otp_app identifier?

A Repo is a GenServer. There’s macro sugar to make this less obvious. GenServers can have state. In this case there is a connection pool involved.

2 Likes

The Repo itself is actually a Supervisor, not a GenServer. It starts a few things and the connection pool is one of those.

At risk of going off on a tangent …

They’re disjoint sets? I’ve always considered Supervisors as specialized subtypes of GenServers :man_shrugging:

I think that specially for authenticated user data that you might be using in many places, you could store in the plug’s conn.assigns

Yeah but basically I canretrieve conn only from the web layer(ie. controllers). I would need to add the user as a paremeter anyway in my phoenix contexts right?

Btw Sorry for late replay.