hagsteel / swampdragon

swampdragon
Other
557 stars 73 forks source link

onChannelMessage never calls #138

Closed valignatev closed 9 years ago

valignatev commented 9 years ago

I wrote simple application which shows currently loggen in users, it works well and I want make it realtime. So I have my model and custom manager:

class AuthenticatedUsersManager(models.Manager):

    def get_queryset(self):
        """
        Get all currently logged in users
        see http://stackoverflow.com/questions/2723052
        """
        sessions = Session.objects.filter(expire_date__gte=timezone.now())
        uid_list = []

        # Make a list of user ids from sessions
        for session in sessions:
            data = session.get_decoded()
            uid_list.append(data.get('_auth_user_id', None))

        # Query all logged in users by id from uid_list

        return User.objects.get_queryset().filter(id__in=uid_list)

class AuthenticatedUser(SelfPublishModel, models.Model):
    user = models.OneToOneField(User)
    objects = AuthenticatedUsersManager()
    serializer_class = AuthenticatedUserSerializer

Serializer:

class AuthenticatedUserSerializer(ModelSerializer):
    class Meta:
        model = 'game.AuthenticatedUser'
        publish_fields = ('username',)
        update_fields = ('username',)

Router:

class AuthenticatedUserRouter(ModelRouter):
    route_name = 'authenticated-users'
    serializer_class = AuthenticatedUserSerializer
    model = AuthenticatedUser

    def get_object(self, **kwargs):
        return self.model.objects.get(pk=kwargs['id'])

    def get_query_set(self, **kwargs):
        return self.model.objects.all()

route_handler.register(AuthenticatedUserRouter)

And controller:

gameControllers.controller('AuthenticatedUserCtrl', ['$scope', '$dragon', function($scope, $dragon) {
    $scope.authenticatedUsers = [];
    $scope.channel = 'users';

    $dragon.onReady(function() {
        $dragon.subscribe('authenticated-users', $scope.channel, {}).then(function(response) {
            $scope.dataMapper = new DataMapper(response.data);
        });

        $dragon.getList('authenticated-users', {}).then(function(response) {
            $scope.authenticatedUsers = response.data
        });
    });

    $dragon.onChannelMessage(function(channels, message) {
        if(indexOf.call(channels, $scope.channel) > -1) {
            $scope.$apply(function() {
                $scope.dataMapper.mapData($scope.authenticatedUsers, message);
            });
        }
    });

    $scope.playerInvited = function(user) {
        user.is_invited = true != user.is_invited;
        $dragon.update('authenticated-users', user)
    }
}]);

So when I log out some user in second browser window nothing happend. Through debugger I realized that onChannelMessage does not called.

Hovever tutorial worked well for me.

valignatev commented 9 years ago

Because of ugly CORS errors I tried to follow Issue #73 with no results. Then I checked that tutorial show me that CORS error too but work well in same time.

gnzlo789 commented 9 years ago

For what I can see in your code your are missing a way to trigger the router so you can send the information you want when a user login or logout. Using a SelfPublishModel will trigger the call to the router but only on CRUD operations to that model, in this case the model affected is Session.

I see you do user.is_invited = true != user.is_invited; but the only field you can update is username, add that field in the model and serializer if you want to trigger an update with your actual approach.

Hope it helps. Bye.

valignatev commented 9 years ago

Using a SelfPublishModel will trigger the call to the router but only on CRUD operations to that model

Thank you. Now it makes sense. I thought it will triggered on any Model.objects.all() change. Never go deep into source. So I have to add another field and change it. See if it works

valignatev commented 9 years ago

Yes it works! Thanks you one more time!