Associations between schemas of different contexts

I have started to think how I would restructure my existing Phoenix 1.2 app into Phoenix 1.3 contexts. One problem I face now with the new contexts is whether or not I can use associations across schemas from different contexts.

I have two contexts and schemas within each as below:

Account

  • User

Auth

  • PasswordAuth
  • SMSAuth

Can I add associations for User schema and PasswordAuth from different contexts or should I continue only using the functions from the contexts files to fetch the schema from other entities.

To be concrete,
can I do this?

defmodule Account.User do
  schema "account_users" do
     has_many :password_auths, Auth.PasswordAuth
  end
end

defmodule Auth.PasswordAuth do
  schema "auth_passwords" do
    belongs_to :user, Account.User
 end
end

Doing the above, I feel like I am crossing the context limits because context1 implicitly depends on the associations set on the schema of context2.

The other option that comes to my mind is to use duplicate user schema within Auth context. But then the generated migration files suggest that schemas are tightly coupled with a database table. I infer this from the table name of User schema inside Account context being called account_users and not just users.

The last option is to not use association across contexts and depend on functions in contexts. In the example above, I would call Auth.add_password(attrs) from Account context to add a password for a given account. However, I cannot rely on the foreign key constraints and validations that are available when I use associations in schema. i.e., I cannot validate if the user_id present in the auth_passwords table actually refer to a valid user or not.

5 Likes

In the described situation, I would first ask - are those really separate contexts if they are tied so tightly?

1 Like

Yes, they are different context. Here is my reasoning but open for your correction :wink:

Account context has the following schemas (I only gave User schema in my post for brevity)

  1. User
  2. ContactInformation
  3. Organization
  4. Preference

An user in Account can have multiple contact info, belong to multiple organisations and has one preference and may or may not have login credentials. Having a login detail for each user is not a requirement.

If the above example is not good enough to reply to my question, consider the use case of

** Sales

  • OrderSchema

** Catalog

  • ProductSchema

can I use associations in my OrderSchema to ProductSchema crossing the boundaries of contexts?

Edit: how to do something like the diagram shown in https://youtu.be/tMO28ar0lW8?t=16m2s. There are multiple schemas duplicated in different contexts. Do they share the same database table? I guess so.

1 Like

I would like to know the answer to this question as well.

The very most classic example that pretty much any single web application has is that a lot of resources / associations belong to a specific user. In my applications the user is, like it or not, omnipresent and the application doesn’t make sense if I can’t scope the resources to a given user.

How does one handle this kind of situation? On paper, having Accounts->User sounds like a great idea, but sooner or later, you’ll need to access it outside of the Accounts context.

1 Like

If that’s the case then do share the user with your other contexts. Bounded contexts are a instrument to devide things that should be devided, not to force things separate which are essential to each other. If your user does interact with all of your context (in the same/similar way), then share it with those contexts. If you have users in your system, which might be Newsletter Subscribers and/or website users, then it might make sense to have dedicated code for both of those concerns.

4 Likes

You can just have a user_id on another context’s resource and then use the Accounts context to access your user resource (Accounts.get_user(user_id) or so). That’s totally valid :slight_smile:

From Phoenix v1.3.0-rc.0 released

4 Likes