In my Sails project, I have a User model/controller and a Request model/controller, as well as a Dashboard controller. A user can make a request for data using RequestController.create, and an administrator can approve it using RequestController.grant.
What I want to do is to notify a user whenever one of his/her requests is approved (updated). In RequestController.grant, I call Request.publishUpdate(...), and in my DashboardController.display, I call
Request.find(req.session.user.id, function(err, requests) {
...
Request.subscribe(req, requests, ['update'])
...
});
Then, in the view /dashboard/display, I put in <script> tags:
<script>
// Socket handling for notifications
io.socket.on("request", function(obj) {
alert(obj.verb);
alert(obj.data);
alert(obj.previous);
});
</script>
However, upon approving a user's request and going to the dashboard, no alerts show up. The script for sails.io is already loaded, with no errors in the console. Am I doing something wrong?
The likely problem here is that you're using Request.subscribe in an HTTP call. I'm assuming that's the case since it seems like you're problem using DashboardController.display to display a view. In this case, the Request.subscribe doesn't do anything at all (it should really display a warning) because it can't possibly know which socket to subscribe!
If you'd like to keep your controller logic the same (you might be using the requests array as a view local to bootstrap some data on the page), that's fine; a quick refactor would be to test whether or not its a socket call in the action:
// Also note the criteria for the `find` query below--just sending an
// ID won't work for .find()!
Request.find({user: req.session.user.id}, function(err, requests) {
...
// If it's a socket request, subscribe and return success
if (req.isSocket) {
Request.subscribe(req, requests, ['update'])
return res.send(200);
}
// Otherwise continue on displaying the view
else {
...
return res.view('dashboard', {requests: requests});
}
});
Then somewhere in your view call io.socket.get('/dashboard/display') to subscribe to request instances.
You could also use blueprints to subscribe to the requests from the front end, doing something like io.socket.get('/request?user='+userId), if you put the user ID in the locals and add it somewhere in your view template, e.g. <script>var userId=<%=user.id%></script>.