Skip to content

Instantly share code, notes, and snippets.

@kellysutton
Last active September 10, 2016 20:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kellysutton/a488068ef32c3b61c59ab081be8b409c to your computer and use it in GitHub Desktop.
Save kellysutton/a488068ef32c3b61c59ab081be8b409c to your computer and use it in GitHub Desktop.
Real-time Recipe for Rails and Ember using Pusher
// app/routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
currentUser: Ember.inject.service(),
pusher: Ember.inject.service(),
activate() {
this._listenToPusherEvents();
},
_listenToPusherEvents() {
const user = this.get('currentUser.user');
if (user) {
this.get('pusher').listenToUser(user);
}
}
});
# app/models/comment.rb
class Comment < ActiveRecord::Base
include PublishesUpdatesToPusher
end
<script src="https://js.pusher.com/3.1/pusher.min.js"></script>
# app/models/concerns/publishes_updates_to_pusher.rb
require 'active_support/concern'
module PublishesUpdatesToPusher
extend ActiveSupport::Concern
included do
after_commit :notify_via_pusher, on: [:create, :update]
def notify_via_pusher
if Sidekiq.server?
PusherUpdateWorker.new.perform(self.class.name, id)
else
PusherUpdateWorker.perform_async(self.class.name, id)
end
end
end
end
// app/services/pusher.js
import Ember from 'ember';
import ENV from 'my-app-name/config/environment';
/* global Pusher */
const { computed, run } = Ember;
export default Ember.Service.extend({
store: Ember.inject.service(),
listenToUser(user) {
if (this.get('hasSubscribedToUser')) {
return;
}
this.subscribe(`User-${user.get('id')}`, "objectUpdated", (data) => {
run.scheduleOnce('afterRender', this, this._pushPayload, data);
});
this.set('hasSubscribedToUser', true);
},
subscribe(channelName, event, callback) {
const channel = this.get('_client').subscribe(channelName);
channel.bind(event, callback);
},
_pushPayload(data) {
this.get('store').pushPayload(data);
},
_client: computed(function() {
Pusher.logToConsole = ENV.environment !== "production";
return new Pusher(ENV.pusher.key);
})
});
# app/workers/pusher_update_worker.rb
class PusherUpdateWorker
include Sidekiq::Worker
def perform(klass, id)
Pusher.encrypted = true
pusher = Pusher::Client.from_env
obj = Object.const_get(klass).find(id)
channel_id = "User-#{obj.user_id}"
resource_klass = Object.const_get("#{klass}Resource")
serialized = JSONAPI::ResourceSerializer.new(resource_klass, {
always_include_to_one_linkage_data: true,
always_include_to_many_linkage_data: true
}).serialize_to_hash(resource_klass.new(obj, nil))
pusher.trigger(channel_id, "objectUpdated", serialized)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment