Pusher + Slanger - Publish away!

Played around with Pusher today.

Surprisingly, it was an easy push. If you haven’t heard about Pusher, it is a hosted API that allows you to quickly build publish-subscribe messaging functionality into your web application. Like most hosted APIs, they work on a freemium model and charge only when you use up to 100 concurrent connections at a time.

Pusher provides a pusher-gem which lets your Rails controllers send out publish messages.

All you need to do is to just:

  1. Setup your Gemfile
# In your Gemfile
gem 'pusher', '=0.10.0' # I'll tell you why I forced a 0.10.0 further down in this post.
  1. Setup your Rails Initializer
# /config/initializer/pusher.rb
Pusher.logger = Rails.logger

# You'll get your key when you sign up your account at pusher.com
Pusher.key = '765ec374ae0a69f4ce44'
Pusher.secret = 'your-pusher-secret'
Pusher.app_id = '36298'
  1. Setup your Pusher Authentication Controller
$ rails g controller pusher
# app/controllers/pusher_controller.rb
class PusherController < ApplicationController
  protect_from_forgery :except => :auth # prevents CSRF check on auth

  def auth
    if current_user
      # Refer to http://pusher.com/docs/authenticating_users for SSD
      response = Pusher[params[:channel_name]].authenticate(params[:socket_id])
      render :json => response
    else
      render :text => "Not authorized", :status => '403'
    end
  end
end

The reason why you need this controller, is because you’d need to make sure the person requesting subscribe access to your private channels actually is who he says he is. You can read about how Pusher handles such requests over here.

What are private channels you ask?

  1. Now that the backend is setup, lets get your front-end subscribed.

In the pages where you’d like to utilize the real-time messaging function, add the following (I’d recommend your app/views/layouts/application.html.erb)

# app/views/layouts/application.html.erb

# within <head>
  <script src="http://js.pusher.com/1.12/pusher.min.js"></script>
  <script type="text/javascript" charset="utf-8">
    $(function(){
        Pusher.log = function(message) {
          if (window.console && window.console.log) {
              window.console.log(message);
                }
                };
        var pusher = new Pusher('765ec374ae0a69f4ce44');
        var channel = pusher.subscribe('loadup'); #loadup is the channel name
        var private_channel = pusher.subscribe('private-'+<%= current_user ? current_user.id : 'null' %>);
        channel.bind('subscription_error', function(status) {
          });
        channel.bind('pusher:subscription_succeeded', function() {
          });
        channel.bind('my-event', function(data) {
            alert('An event was triggered with message: ' + data.message);
            });
        private_channel.bind('pusher:subscription_error', function(status) {
          });
        });
  </script>
  1. Once that’s done, when you load up and run your app, you should see the following in your console (Chrome Developer Tool/Firebug)
Pusher : Connecting : ws://localhost:8080/app/765ec374ae0a69f4ce44?protocol=5&client=js&version=1.12.5&flash=false dashboard:138
Pusher : State changed : connecting -> connected dashboard:138
Pusher : Event sent : {"event":"pusher:subscribe","data":{"channel":"loadup"}} 

This tells you, you’re subscribed!

  1. Lets test run sending a message.
$ rails console
>> Pusher['loadup'].trigger('my-event', {:message => "Hay guys"})
=> true
  1. Right as you hit enter in the above trigger command, you should see a alert popup straightaway, bringing your browser window into focus.

And that is the magic.

Wait, so why did you tell me to force pusher to 0.10.0 in my Gemfile?

Good question! Thanks for reminding me.

Now, I’m going to introduce you to a open-source implementation of pusher. This allows you to run your own pusher instance without relying on Pusher.com’s hosted API.

What this means is that you are going to be able to work on your pusher app in development mode even when you don’t have internet connection. It also means that if you deploy it to production, you don’t need to pay Pusher.com if you have > 100 users.

Introducing, Slanger.

I’m not going to repeat the steps here because they are pretty straightforward. To set it up, just follow the instructions at their github page.

You’re going to need Pusher 0.10.0 because for at this point of time, Pusher 0.11.x is not compatible with Slanger. (see Issue #84)

Make sure in your Gemfile.lock after doing a bundle install, you edit and make sure that the signature gem is using version 0.1.4 as 0.1.6 is not compatiable with Pusher 0.10.x.

Note that, because the tutorials in Pusher’s Github page is based on 0.11.x, you will not be able to use Pusher.trigger('channel', 'event', 'message'). Instead you’re limited to Pusher['channel'].trigger('event', 'message').

Hopefully this gets fixed soon though.

Resources: