How to return boolean from this promises cake layer?
I have a controller method that takes a string argument, so I can check if the user has the option. The user has many roles, and the roles have an array of permissions that we need to check if they contain this capability. I know this is too verbose, but for the sake of understanding, I left it that way. Will there be refactoring later ...
App.WorkspaceIndexController = Ember.Controller.extend({
userCan: function(capability) {
var userHasCapability = false;
var userPromise = this.get('session.user');
var rolesPromise = userPromise.then( function(user) {
return user.get('roles');
});
var filteredRolesPromise = rolesPromise.then(function (roles) {
return roles.filter(function (role) {
return role.get('workspace') === self.get('workspace');
});
});
filteredRolesPromise.then(function (filteredRoles) {
return filteredRoles.forEach(function (role) {
userHasCapability = _.contains(_.flatten(role.get('permissions'), 'name'), capability);
});
});
return userHasCapability;
},
...
});
The problem I am facing is that I need a method to return boolean if the user has permission. This returns false every time. Am I setting the userHasCapability property incorrectly, or is there something else I have to do to return the value?
source to share
Primitive types like bool, int, string, etc. are copied without reference. This means that you return userHasCapability
and false is returned immediately, setting userHasCapability
within that promise does not mean it will be returned. It really won't.
Also, the real answer must be in the form of a promise, and whoever calls will have to use it in that form as well.
Here is the order of operations, if foo
called userCan
.
App.WorkspaceIndexController = Ember.Controller.extend({
foo: function(){
var j = this.userCan('eat worms'); // 1. method is called, 6. j is set to false, we fall out of foo
},
userCan: function(capability) {
var userHasCapability = false;
var userPromise = this.get('session.user');
var rolesPromise = userPromise.then( function(user) { // 2. promise built
return user.get('roles'); // 7. this promise happens is resolved
});
var filteredRolesPromise = rolesPromise.then(function (roles) { // 3. another promise built
return roles.filter(function (role) { //8 return the filter cause 7 resolved
return role.get('workspace') === self.get('workspace');
});
});
filteredRolesPromise.then(function (filteredRoles) { // 4. another promise built
return filteredRoles.forEach(function (role) { //9. 8 resolved so do this now, even though no one references userHasCapability anymore
userHasCapability = _.contains(_.flatten(role.get('permissions'), 'name'), capability);
});
});
return userHasCapability; // 5. false is returned
},
...
});
The fact that roles are a promise means that anyone trying to use it should expect the result to be a promise (or not use async and not use promises)
App.WorkspaceIndexController = Ember.Controller.extend({
foo: function(){
this.userCan('eat worms').then(function(result){
console.log(result);
});
},
userCan: function(capability) {
var userHasCapability = false;
var userPromise = this.get('session.user');
var rolesPromise = userPromise.then( function(user) { // 2. promise built
return user.get('roles'); // 7. this promise happens is resolved
});
var filteredRolesPromise = rolesPromise.then(function (roles) { // 3. another promise built
return roles.filter(function (role) { //8 return the filter cause 7 resolved
return role.get('workspace') === self.get('workspace');
});
});
return filteredRolesPromise.then(function (filteredRoles) { // 4. another promise built
filteredRoles.forEach(function (role) { //9. 8 resolved so do this now, even though no one references userHasCapability anymore
userHasCapability = _.contains(_.flatten(role.get('permissions'), 'name'), capability);
});
return userHasCapability;
});
}
});
source to share