Please forgive the somewhat simplistic thread title. What I’m really asking is how do you all design your contexts with regard to schemas and changesets? And similarly how do you expose DB interactions via contexts?
Let me give you an example, many Phoenix projects will have the following context setup:
/accounts
accounts.ex # Contains public interface for context and functions which use 'Repo'
user.ex # Contains user schema and changesets
Now let’s suppose we add a new ‘WorkExperience’ association to a ‘User’. i.e. a User has_many WorkExperience’s, and each WorkExperience belongs_to a User.
Work experience code is rather complicated and not obviously accounts related so we add a new context like so:
accounts/
accounts.ex # Contains public interface for context and functions which use 'Repo'
user.ex # Contains user schema and changesets
work_experiences/
work_experience.ex
We now add a form to edit a user’s WorkExperience, where should the business logic and changeset go for this?
The ‘easy’ choice would be as follows:
# accounts.ex
def set_work_experiences(%User{} = user, params) do
user
|> User.work_experiences_changeset(params)
|> Repo.update()
end
But now we are adding non-account related functionality to the Accounts context. This also doesn’t scale as we add more complicated associations to the User (in our case the User schema is quite complicated).
Here’s one possible solution to this problem:
user/
user.ex
accounts/
accounts.ex
work_experiences/
work_experience.ex
i.e. Don’t store the User schema in Accounts but separate it out into its own context. This context could contain the schema and functions to update the User table. We can then leave User changeset definitions to whichever context is most appropriate. e.g.
# work_experience.ex
def set_work_experiences(%User{} = user, params) do
user
|> work_experience_changeset(params)
|> User.update()
end
Apologies for the lengthy post. Does anyone have any thoughts/experience with this? It’s hard to find info for how people are organizing contexts at scale. It’s very possible I’m missing something obvious.
Thanks in advance!