achempion

achempion

This pattern is very similar to ActiveRecord, the ORM from Ruby on Rails framework.

Basically, you can do things like this

User
  .where(is_admin: true)
  .order(email: :asc)
  .update_all(ia_admin: false)

The context approach is something different, you abstract all the query construction behind the semantic function name and you can explore all the queries just looking into context files.

If you’re going to create “meta” contexts then we’ll go back to the ActiveRecord pattern where queries are constructed elsewhere in your codebase but not in one single place.

Both approaches have pros and cons but I don’t think mixing them is a good idea. For me it’s two completely different things because in one case you have “the right way” and you’re overindulging yourself in all king of helpers and pre-generated code.

I can’t find it right now but can remember when rails had code like def seven(), do: 7 and you could write seven.days.ago or something similar. It does create pleasant experience but empirically it’ll end up in a codebase which is implicit and challenging to maintain.

On the other side, I comprehend Elixir approach like be explicit, be flexible, allow user decide what is best and how to approach problems and it work best when you’re experienced engineer. Finally, we have configurable, explicit and flexible interfaces in Elixir ecosystem.

0
Post #11
1player

1player OP

I haven’t used ActiveRecord in a decade, but the point of contexts is separating the business logic from the rest of the application. Multiple query functions or the design pattern described here are still miles better than the regular usage of ActiveRecord, in that it is usually called in the controllers, making tests more difficult as you then require a database connection.

This pattern comes natural if you need to integrate Absinthe GraphQL + dataloader in your application, and it made sense to me to use the same logic even for regular Ecto consumers that are not necessarily connected to Absinthe.

In any case, as with most design patterns, there is No True Way, and I find having a small amount of functions in my contexts better for tests, as contexts are usually the API/contract to test against, and the fewer the functions, the easier it is to mock against.

1
Post #12
— All posts loaded —