Realtime Support for Rails
This gem enables you to communicate with your rails front-end in realtime, leveraging socket.io, redis (or ZeroMQ), and node.js. Clients are authenticated via their user id plus a day-long shared session token between the servers.
Note: This gem is a concept piece originally conceived in 2013 and published as a generic open source project in early 2014. As of mid-2015, support for performant, native and scalable websockets are available in Rails. See ActiveCable ActionCable, which landed in Rails 5 and will probably be officially released early/mid 2016. As such, with ActionCable
's design, you don't even need a separate pub/sub server (redis) and Node.js running anymore to achieve similar lightweight realtime bi-directional communication with a large number of connected clients to your Rails application. Progress marches forward! I presume, if you are stuck and can't upgrade to Rails 5 anytime soon, perhaps this project is lightweight compared to some of the heavier alternatives like Faye or PubNub.
This gem, and sample node.js servers were inspired by the blog post: Liam Kaufman's Adding Real-Time to a RESTful Rails App.
A live demo of this in action using redis is at Realtime-rails Demo on Heroku. A diagram of this in action:
A live demo of this in action using ZeroMQ is at Realtime-rails-zmq Demo. A diagram of this in action:
To start, install the gem in your Gemfile:
gem 'realtime'
If you want to use redis for your realtime backend, first, install redis:
For OS X, with homebrew:
brew install redis
For more information on installing redis locally on other platforms, see http://redis.io/topics/quickstart
next, include in your Gemfile
:
gem 'redis'
and then run:
bundle install
If you want to use embedded ZeroMQ for your realtime backend, you'll need to install ZeroMQ, and then include:
gem 'zmq'
gem 'em-zmq'
and then run:
bundle install
Next, you'll need to tell your application_controller.rb
that it is sharing a realtime token with your realtime server by adding the following lines:
# app/controllers/application_controller.rb
realtime_controller({:queue => :redis}) # instruct all requests to enable realtime support via redis
# realtime_controller({:queue => :zmq}) # instruct all requests to enable realtime support via zmq
def realtime_user_id
return 42 # if using devise, change this to current_user.id
end
def realtime_server_url
# point this to your node.js-socket.io-redis/zmq realtime server (you can set this later)
return 'http://your-realtime-server.yourdomain.com'
end
In your application.html.erb
file, add the following to your <head>
element:
<!-- required: realtime support framework -->
<%= realtime_support %>
<!-- optional: message_handler dequeues realtime messages into Backbone.js style events -->
<%= realtime_message_handler %>
<!-- optional: message_console_logger listens or dequeues realtime messages to the browser console -->
<%= realtime_message_console_logger %>
If using redis, tell rails about your redis instance:
# config/initializers/redis.rb
location = ENV["REDISCLOUD_URL"] || 'redis://127.0.0.1:6379/0'
uri = URI.parse(location)
$redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
If using ZeroMQ, tell rails about the ZeroMQ endpoint:
# config/initializers/zero_mq.rb
$zero_mq = "tcp://zmq-server.mikeatlas.com:5556"
Now, you'll need to run a realtime node.js server (you can use my sample realtime server). If you host this Node.js server on Heroku, you'll need to enable websockets for this application.
gem install foreman
git clone git://github.com/mikeatlas/realtime-server.git
cd realtime-server
sudo npm install
foreman start
If you want to use the ZeroMQ enabled realtime server, you'll probably run into trouble standing it up on Heroku since the library is not installed on the Cedar stack by default, so my recommendation is to run it on an Amazon EC2 instance (be sure to open up ports 80, 5001, 5556 and 5557). You'll need to install ZeroMQ, and run:
gem install foreman
git clone git://github.com/mikeatlas/realtime-server-zmq.git
cd realtime-server-zmq
sudo npm install
foreman start
Now that you have rails running and connecting to redis/ZeroMQ, and node.js running and connecting, you should be able to try it out. Connect to your rails console rails c
and run the following command:
# if using redis:
$redis.publish 'realtime_msg', {msg: 'hello world - ' + SecureRandom.hex, recipient_user_ids: [41, 42]}.to_json
# if using ZeroMQ:
ZmqWrapper.publish({msg: 'hello world - ' + SecureRandom.hex, recipient_user_ids: [41, 42]})
If you are user id 42
in the rails application, you should see in your browser console something like:
Object {msg: "hello world - e008f94a8710826bad8c4f6af28be922"}