I am trying to learn about the scopes added in Phoenix v1.8.0rc3.
I am testing a backlog application and I was thinking on adding a scope that makes sure that there is a defined product for the backlog, and that can add some specific information about configuration, instead of adding it to the parameters every time, and providing some consistency (i.e. I can put there the preferred view type - card, table, etc) so that I can navigate maintaining consistency.
Does it make sense? Would that be a good use for scopes?
If it does make sense, would it be necessary to add it to the current_scope, or should I use a separated scope? I am anyway using the user scope, so I want to understand if it makes sense to add a new one and use both in every call.
Personally I find it best to keep scopes to authorization and environment based things, otherwise you risk bloating the scope (is this called scope creep?
) and can end up making a whole other kind of mess where you are passing too much around. I put things like the current user, the tenant, user settings, the locale, etc. A lot of this stuff you could get through the user but putting it right on scope is more flexible and easier to refactor down the line. I also find it best that scope keys are always populated. For example, if you have two structs that represent different types of users, put the appropriate one in current_scope.user
, otherwise you’re going to have nil
/presence
checks everywhere and avoid having to make helper functions to get the right thing. This is a mistake I’ve made before (and is currently being made at work, lol).
2 Likes
That was my intention, only the environmental information that would make the user choice available independent of the navigation (i.e. the project you are editing). Basically what you said, tenant, locale, etc…
My question is about whether it is designed to use the same context (as the default is already there) or if it would be better to have more than one context in parallel, one for the authentication and another for the rest. I saw the generators and the on_mount call and I was wondering if it makes sense to duplicate the logic for the second context
Oh I see. Honestly, I’m not sure of the point of multiple scopes. I saw that it is possible but haven’t looked into it, so I guess I have the same question, lol. I’ve been using this pattern for almost a decade now and never felt the need for multiples.
That is my fault, I always find these questions…
I was thinking that one can be a security context (user, access, etc), and the other a configuration context (preferred view, project, etc). So you can be more strict with the security context, but I don’t know if that idea makes sense
Ya I’m really not sure as I’ve never felt that need. Do you have an example of how you are thinking you would use it? If not I would wait until it becomes a pain point, otherwise I can see it complicating things immensely. The scope pattern has the nice benefit of only needing to pass one arg. As soon as you bring another scope into the mix, then you need to know which functions require which scope. I think it’s far better to just think of scope as a bag of global variables you are keeping a tight leash on, so it’s totally ok if not every function uses every part of the scope.
As an aside, Rails’ version of “scope” actually does implement it as a global object called Current
. Well, it’s a “singleton,” though that’s just another name for global to make people feel better about using them 
2 Likes
It makes sense. I will then add things to the scope instead of trying to have another.
Thanks
Not sure I’d give me the checkmark yet here, I’m still also curious as to what the usecase for allowing multiple scopes is!
Are scopes like bounded contexts or subdomains in DDD?
I saw the keynote from Jose Valim on 1.8 and scopes and he states that you add any information to the scope, following the pattern you suggested with a single context.
My train of thought:
- The default scope is in Accounts, not in Application, so it seems to be specific to the Account session. Immediately I thought it is a good place to store account related and security related information, outside of the parameters of the query. The fact that
phx.gen.auth
uses it to restrict what a user can query is a good example.
- My thoughts moved to think that I should substitute that with a function when I have more complex queries (i.e. I can see what others do, but not modify it)
- Then I thought that I needed a context in my application to restrict searches not for security but to avoid the interface forgetting about configuration between navigations or after refresh (i.e. I want to use the card view, next page I visit will use the card view and not the table view). I didn’t think that context belonged to “Accounts”, because I can be a guest and still use it, so I decided to use a secondary context.
- This last context is not related to log in. People can view things navigating without logging in and still have a context so the experience is good.
Perhaps it is that I think of the Accounts context as a Session context, that makes more sense to me, and the name was leading me to a different place