I would love to hear other opinions on this, but I think the key thing here would be that the contexts do not specifically know about %Plug.Conn
.
You definitely don’t want this context function signature…
def create(%Plug.Conn{} = conn)
You could be less specific about it and grab things out of a struct that just happens to have the same structure as a conn if it really makes sense for your context API, but it almost surely does not…
def create(%{assigns: %{organization: organization, user: user, token: token}})
However, this is coupled to the structure of a conn and doesn’t seem like clean arguments for the context function.
You could pass just the assigns so as not to reach deeply into the struct…
def create(%{organization: organization, user: user, token: token})
But you are still reliant on how the conn is built up on the web side of your app and it is still arguable whether this is a clean way to take arguments in the context function.
Try to imagine you didn’t have a web interface for your app at all and were only designing the context function. How would you want the function signature to operate? Let that dictate what/how arguments are passed in.
For instance, maybe a function signature like this makes more sense in your app…
def create(%Organization{} = organization, %User{} = user, token})
This should be more resistant to breakage due to changes in the controller because you will have been explicit of the needs of the function at the boundaries.