coen.bakker
I read the Hexdocs about contexts in Phoenix. Now that I revisit my own code, across different projects, I notice that I sometimes use Repo functions outside my context modules.
Like so:
# example 1
item =
conn.params["id"]
|> SomeContext.get_item!()
|> Repo.preload(:users)
# example 2
item =
params["id"]
|> SomeContext.get_item!()
|> Repo.preload([users: from(u in User, select: u.username)])
Is that an anti-pattern?
My thoughts.
- It reads easily the way it is.
- But I don’t like that I have to
import Ecto.Query, only: [from: 2], warn: falseandalias TodayCostory.Repointo my controller/LiveView to be able to use theRepofunctions. - In some cases I would get quit a few additional functions inside my contexts. Taking the examples from above: get_item_with_users!() and get_item_with_usernames!(). Seems somewhat unnecessary.
- But maybe the benefits of having a context, and using it without compromise, is ultimately greater than the potential downsides. Most importantly, maybe, the benefit of creating greater separation of concerns.
Trending in Questions
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello,
I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Most Liked- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
sodapopcan
I’m firmly in the camp of keeping Repo calls inside contexts and, more specifically, only in context files (or sub-contexts). For example, as you probably already know, they don’t belong in schemas.
I usually do this type of thing to provide options to the client:
then:
This takes advantage of ecto ignoring
niloptions (so you don’t have to pass:preload).I’m admittedly on the fence about this since it is still exposing parts of ecto to the client, but I haven’t worked on a big enough project to where I can confirm how this plays out. It’s also not so bad since generally you are only specifying relationships as data which the client already knows anyway.
This also doesn’t address preloading with a select, so in this case you’d need to make a custom function for the specific scenario. I, admittedly, never worry about loading more columns than I need as I’ve never worked on anything where those types of optimizations made any kind of noticeable difference (this is especially not as big a problem with LiveView since the extra fields aren’t being sent to the browser). It is, however, something I have thought about more than a few times and would be super interested to hear what other people do.
EDITED to add the default
[]foropts, which is pretty critical.eahanson
I typically try to keep my repo function calls in my contexts. I my apps, I’d write your example code like this:
Sometimes the preloads can get complex (eg, preload some deep associations and sort everything correctly), so putting them somewhere outside of the UI code makes them easier to find for later reuse.
zachallaun
I really like the solution/technique you proposed. Regarding this particular worry, I think you’re in the clear by “allowlisting” the repo options that you accept, like you do with
:preloadhere. This isn’t fundamentally any different thandefdelegateto export a function from a nested module. You’re essentially just making that specific option a part of your public API. I think where it would be a problem is if you passed opts directly to the repo, which you of course aren’t doing.Last Post!
sodapopcan
Honestly I picked this up largely from a post I read here at some point, I just can’t find where, so while I don’t want to take all the credit, I don’t know who to credit.