With the increasing expectation of web-applications, everyone wants real time updates or real time notifications to improve the web portals user experience. Understandably, my project required Real time notifications too. I successfully implemented and deployed on production. During my development I found some interesting gems, javascript libraries that I came across. So I thought it would be helpful if I share my experience. To make it more useful I have created a sample repository for demonstrating Real Time notifications for your further reference.
The AIM: Notify the user with a reminder on specific user defined date and time using Web notifications.
I choose slanger gem. (Recently updated by Jiren to make it compatible with rails4). To make it work, add pusher to rails app and for slanger instead of adding it in rails Gemfile
, I created a sub directory called ‘slanger’ in my rails project and added slanger. Now we are done with installation. Now let’s see some configuration:
#config/initializers/pusher.rb Pusher.app_id = app-id Pusher.key = app-key Pusher.secret = app-secret Pusher.port = 4567 Pusher.host = 'localhost'
where app-id, app-key and secret could be any secure random number for authentication purpose.
Note: Add the IP address of the machine if your running app is in production mode or staging mode.
Now it’s time to add a sidekiq job to push notifications on a particular user defined time. Here is code snippet how to add sidekiq job:
# app/models/reminder.rb class Reminder include Mongoid::Document field :text, type: String field :notify_at, type: Time after_create :add_sidekiq_job before_destroy :remove_sidekiq_job def add_sidekiq_job id = ReminderWorker.perform_at(scheduled_at.second, {id: self.id.to_s}) self.update_attributes(job_id: id) end def remove_sidekiq_job queue = Sidekiq::ScheduledSet.new job = queue.find_job(self.job_id) job.delete if job end def scheduled_at notify_at.to_time.to_i - Time.now.to_i end end
The above code snippet adds a sidekiq job after reminder
object has been created.
Now let’s trigger some notifications:
# app/worker/reminder_worker.rb class ReminderWorker include Sidekiq::Worker def perform(args) reminder = Reminder.find(args['id']) Pusher.trigger("reminder", "reminder_12345", {notification_text: "Reminder: #{reminder.text}"}) end end
where trigger
takes three arguments. First argument is ‘channel’ and second argument is ‘event’ and third one is data that you want to push to client.
Note: reminder_12345
is a unique way to identify to which user we have to push notification.
Once data has been published on channel the browser should respond and display data on front end. To do this every client should subscribe reminder
channel using following javascript snippet:
#app/assets/javascripts/remainder.js var reminder = pusher.subscribe('reminder');
Prior to subscribe, pusher needs to authenticate. To do this, use following snippet:
# app/assets/javascripts/remainder.js window.pusher = new Pusher(PUSHER_API_KEY, {authEndpoint: '/pusher/authentication', authTransport: 'ajax',activityTimeout: 120000, disableStats: true});
Where PUSHER_API_KEY
would unique key to identify your application. To know more about the remaining options please go through this.
Once you authenticated, client should respond once pusher triggers(nothing but event) a notification. To achieve this use following snippet:
#app/assets/javascripts/remainder.js reminder.bind('reminder_12345', function(data){ $.notify(data['notification_text']); });
Once you watched above code snippet carefully you will get doubt about what is $.notify
and why we need it?
notifyjs is a beautiful javascript library to display notifications on your front end. To know how to customize your notifications please go through the documentation.
So finally coalition of sidekiq
, slanger and notifyjs
has done job for me. It would be great if you share your thoughts on this coalition. Do play around with the demonstration on Github to see this in action.