0

I have a user model which has 2 relations (myFriends and friendsWithMe). The intersection is the Array of users which represents the real friends. I have solved this Computatation with RSVP.all :

friends: function() {
    var ret = [];
    Ember.RSVP.all([this.get('myFriends'), this.get('friendsWithMe')]).then(function(results) {
        ret.pushObjects(_.intersection(results[0].get('content'), results[1].get('content'))) ;
    });
    return ret;
}.property('myFriends.@each', 'friendsWithMe.@each'),

The Problem is now I have another computed property that depends on this one:

/**
 *  Gives the relation between two User
 *  4: has requested your friendship
 *  3: Yourself
 *  2: Friends
 *  1: FriendShip Request
 */
myFriendshipStatus: function() {
if(this.get('friends').contains(this.container.lookup('user:current'))){
    return 2;
} else if(this.get('friendsWithMe').contains(this.container.lookup('user:current'))){
    return 4;
} else if(this.get('myFriends').contains(this.container.lookup('user:current'))){
    return 1;
} else if (this.get('id') === this.container.lookup('user:current').get('id')){
    return 3;
} else {
    return 0;
}
}.property('friends.@each')

When I now debug myFriendShipStatus the promises are not resolved and the "friends" array has no entries yet.

I have also tried to change my friends function to the ember.computed.intersect, which would then look like this:

friends: function() {
    return Ember.computed.intersect('myFriends', 'friendsWithMe')
}.property('myFriends.@each', 'friendsWithMe.@each'),

But then I get an exception from this line:

if(this.get('friends').contains(this.container.lookup('user:current'))){

Because the ArrayComputedProperty has no function contains.

How can get my friends function together with myFriendShipStatus working? I would prefer to use Ember.computed.intersect, but I don't know how I check then for it's values.

m0c
  • 2,180
  • 26
  • 45

1 Answers1

0

The reason it returns an empty array in the first example is as follows. Immediately after the Ember.RSVP.all() call, the return statement will be executed, returning an empty ret array. At some point in the future the RSVP promise will fulfill, but since the friends function has already returned the empty array, this will have no effect.

Here is what you could do:

// See http://emberjs.com/api/#method_A
friends: Ember.A,

recalculateFriends: function() {
  Ember.RSVP.all([this.get('myFriends'), this.get('friendsWithMe')]).then(function(results) {
    var myFriends = results[0], friendsWithMe = results[1];
    this.set('friends', _.intersection(myFriends.get('content'), friendsWithMe.get('content')));
  });
}.property('myFriends', 'friendsWithMe'), // @each is redundant here

myFriendshipStatus: function() {
  // Will be recalculated when the friends array changes (which will in turn recalculate when myFriends or friendsWithMe changes
}.property('friends'),

And... I'm just now noticing you're using Ember.computed.intersect wrong :P It shouldn't be wrapped inside a function:

friends: Ember.computed.intersect('myFriends', 'friendsWithMe')

(See example: http://emberjs.com/api/#method_computed_intersect),

Thomas Brus
  • 931
  • 5
  • 11
  • When using Ember.computed.intersect correctly its working perfectly fine, at least the friends part. But while debugging myFriendShipStatus the "this.get('friends')" is still always an empty Array. But I thought the friendshipstatus is recalculated automatically when my intersect fulfills. – m0c Dec 31 '13 at 16:16
  • Perhaps try adding @each after all? Thought it was redundant – Thomas Brus Dec 31 '13 at 18:16
  • now the function is triggered correctly but the contains check is not working. I have checked the data in the debugger and my computed properties contain the current user, but the contains is somehow not working correctly. – m0c Jan 01 '14 at 16:35
  • Could you post the output of this.get('friends') and this.container.lookup('user:current')? Also, it makes more sense to have a friendshipStatus(otherUser) method, I would say. – Thomas Brus Jan 01 '14 at 17:19
  • If you inspect user:current, you'll find that it is a promise object. That's why the `contains` function fails. So you'll have to make sure you're registering an actual user object in the initializer. For example via `container.register('user:current', store.createRecord('user', App.User.FIXTURES[0]));` – Thomas Brus Jan 01 '14 at 20:34
  • ok,thanks! That would be the solution for now, but how would I handle this if I am changing to a real rest api from my fixtures? – m0c Jan 01 '14 at 21:46
  • Something like `container.register('user:current', null)`, Then in the application route, for example, you'll fetch the user and override user:current (`store.find('user', id).then((user) => ...)`. Note that it might be handy to create a `isSignedIn` helper method that checks whether user:current is present:) – Thomas Brus Jan 02 '14 at 02:25
  • hmm the problem is, that my user:current would then be null if the status is determined. I would like to get the currentUser into my model in order to "observe" it that the status could change as soon as my currentUser is fetched. I already tried it with the container: container.injection('user:model', 'currentUser', 'user:current'); – m0c Jan 06 '14 at 13:45
  • Seems like the original question is answered! Can't help you any further with this. Maybe ask as a separate question? – Thomas Brus Jan 06 '14 at 14:05