-
Notifications
You must be signed in to change notification settings - Fork 7
Notes on Pusher websockets
#Pusher set up in application
Our application allows users to create events with questions. A link to the event is sent out to audience members and from the Event main page the user can publish the question and it will appear on the audiences event screen. We used pusher to do this.
##back end rails set up
gem "pusher" required in the gemfile.
Then in config/initializers/pusher/rb the pusher keys (which you need to get off of pusher) are kept.
Pusher.app_id = 'APP ID'
Pusher.key = 'KEY'
Pusher.secret = 'SECRET'
We gitignored this file for safety. Heroku has really good Pusher integration so if you host on heroku you can set up your own keys via Heroku. Will be a separate pusher account from the dev one.
##How Pusher was used for publishing questions to voters
In the view of of the even page there javascript that connects the client to a websocket hosted by pusher.
pusher = new Pusher('8881c0f8a42807b64625', {
encrypted: true
});
We have had to include pushers JS libary for this to work. The number in the string in the snippet above is the id to connect and listener to the account on pusher our application uses. The page is connected to pusher now not through http response but through a TCP connection. This means the page does not have to be refreshed for the data to be sent and no AJAX does any hidden calls in the background.
There is also another javascript method which the view will get(all via rails asset pipeline of course) which triggers a function dependant on anything that gets sent to the page from pusher.
#subject to change as we refactor
channel = pusher.subscribe('test_channel');
return channel.bind(myEvent(), function(data) {
console.log('message received');
$('#testing').text(data.test);
$('#question-number').text(data.question.id);
$('#question-title').text(data.question.content);
$('#choice-1-text').text(data.choices[0].content);
$('#choice-2-text').text(data.choices[1].content);
});
the function above will trigger the methods within it when it receives something from pusher. This is called a message by pusher and will be a JSON object. In our case the JSON objects holds the question information(title, number and choices of answers). The methods triggered populate a form on the page using JQuery .
Important to understand as soon as the JSON is received the JQuery changes the page.
##Pushing JSON to pusher
To get the question JSON to listener there is a pusher triggering method in the rails controller. When a user clicks on the event page to publish a question it calls a set of methods in rails. These methods creates the JSON as required for the question and event and then pass that JSON to a method which sends the JSON to pusher on the appropriate account and channel
def push_json_to_pusher(json_object, event_id)
pusher = Pusher::Client.new app_id: Pusher.app_id, key: Pusher.key, secret: Pusher.secret
pusher.trigger('test_channel', 'event_' + event_id.to_s, json_object)
end
It gets the keys and ids from our secrets file and then pushes the JSON up to pusher. As soon as pusher gets it any clients connected on the channel will also get it.
Please note that on our application we have send unique event ids with each pusher push. This is to ensure that only voter connected to a specific event get the question for that event.
#testing
After having a look at the pusher fake example here is one approach we can take to testing pusher.
Gemfile we need under test: gem "pusher-fake"
requires a file called spec/support/pusher-fake.rb this contains:
require "pusher-fake/support/rspec"
pushers faker example has an helper method for the tests to connect to pusher.
https://github.com/tristandunn/pusher-fake-example/blob/master/spec/support/helpers/connect.rb
The way they determine which environment they are in is a bit strange. This is because it's in the erb of the index.html.erb. They've put code for the test environment in the production code.
<% if defined?(PusherFake) %>
Pusher.instance = <%== PusherFake.javascript %>;
<% else %>
// Other environments, such as production.
<% end %>
What I am understanding it does is gets PusherFake to run if in the test environment. Feels a bit dirty as the line above is some javascript to get the window listening. The same thing that $(document).ready does with jquery
window.addEventListener("DOMContentLoaded", function() {
not a fan of JS in the erb. But if no other way willing to take a look.
#Creating Forms
interesting way to use pusher to create li elements in a ul
We could use this same make method to make the multiple choice answers appear.
Chat = Pusher.instance.subscribe("chat");
Chat.bind("message", function(message) {
var list = document.getElementsByTagName("ul")[0],
item = document.createElement("li"),
text = document.createTextNode(message.body);
item.appendChild(text);
list.appendChild(item);
});
https://www.new-bamboo.co.uk/blog/2010/05/21/integrating-pusher-into-a-complex-app-in-one-day/