Naming Elixir Phoenix context functions
stephenlewis.me
stephenlewis.me
This may just be the simplicity of the example they have, but they also have an `update_changeset`, which I think is an anti-pattern. You should be creating a different changeset for each operation that can be applied to a given schema. In the case of a user, you may be able to change a password, or an email address separately from being able to change a screen name or something. You should be creating separate changeset functions for each of those operations.
The author also puts a foot note at the end stating that they would usually create a `base_changeset` function that can be reused for common parts of a changeset. Please don't do this. Just create multiple reusable functions for each check. For example, you may create private functions in the schema for `validate_email`, `validate_password`, etc. These are the reusable pieces that you most likely want to have and can be used from within any changeset. Then you will be able to mix and match them as needed instead of trying to come up with a truly base changeset that applies to everything and still have a lot of validation rules duplicated between various changesets.
I disagree that it's an anti-pattern. I'm already making a distinction between a "create" and an "update" changeset, as these may have different validation rules.
Of course, some situations may warrant separate changesets for operations on individual fields (updating an email address, updating a password, etc.), but in practise I rarely find this to be useful.
> Please don't do this. Just create multiple reusable functions for each check.
It's worth noting that these aren't mutually exclusive approaches; we regularly use both on my current project.
I forgot to mention, whenever I see Ecto schema structs bubbling up to the views, I want to throw up.
How else would you do it? It would seem to me (admittedly, naively) that anything else would introduce an unnecessary extra layer between the context and the view. What am I missing?
If your application is a simple CRUD app, then yes, bubbling up Ecto schema structs to the vies is sufficient.
My understanding of contexts (from the docs) is that they are intended to "...encapsulate data access and data validation." They're intended to be the layer of your application that talks to the database. Do you have a different approach?
Re: the sibling comment referring to queries, nothing you’re doing in the article prevents that.
Ecto’s changesets are often an unfamiliar concept, so I wonder if that’s where some confusion is coming from.
However, what you say about having different changesets for validation seems to make a ton of sense to me and has given me some ideas. Thanks.
I don't think this is a terrible idea but I like to draw boundaries and say "It's ok to reach one level deep from any point in the context tree".
ie App.Chat.send_message/2 is cool, but MyApp.Chat.Messages.send_message/2.
Because the context is the “public API” for the rest of your application to use. You can have as many layers below the context as you want, often purely functional, composable, and testable.