Websocket-Rails
Now with streaming HTTP support for improved browser compatibility
The Present
Start treating client side events as first class citizens inside your Rails application with a built in WebSocket server. Sure, WebSockets aren't quite universal yet. That's why we also support streaming HTTP. Oh, and if you don't mind running a separate process, you can support just about any browser through Flash sockets without changing a line of code.
The Future
The long term goal for this project is simple. Reduce the need to move application logic on to the client while still providing the same level of interaction and responsiveness users have grown to expect from a modern web application. We hope to isolate the responsibility of JavaScript to the presentation layer and keep business logic nicely organized on the server.
Installation and Usage Guides
- Installation Guide
- Event Router
- WebsocketRails Controllers
- Using the JavaScript Client
- Using Channels
- The DataStore
- Multiple Servers and Background Jobs
- Standalone Server Mode
A Brief Tour
Map events to controller actions using an Event Router.
WebsocketRails::EventMap.describe do
namespace :tasks do
subscribe :create, :to => TaskController, :with_method => :create
end
end
Trigger events using our JavaScript client.
var task = {
name: 'Start taking advantage of WebSockets',
completed: false
}
var dispatcher = new WebSocketRails('localhost:3000/websocket');
dispatcher.trigger('tasks.create', task);
Handle events in your controller.
class TaskController < WebsocketRails::BaseController
def create
# The `message` method contains the data received
task = Task.new message
if task.save
send_message :create_success, task, :namespace => :tasks
else
send_message :create_fail, task, :namespace => :tasks
end
end
end
Receive the response in the client.
dispatcher.bind('tasks.create_success', function(task) {
console.log('successfully created ' + task.name);
});
Or just attach success and failure callbacks to your client events.
var success = function(task) { console.log("Created: " + task.name); }
var failure = function(task) {
console.log("Failed to create Product: " + product.name)
}
dispatcher.trigger('products.create', success, failure);
Then trigger them in your controller:
def create
task = Task.create message
if task.save
trigger_success task
else
trigger_failure task
end
end
If you're feeling truly lazy, just trigger the failure callback with an exception.
def create
task = Task.create! message
trigger_success task # trigger success if the save went alright
end
That controller is starting to look pretty clean.
Now in the failure callback on the client we have access to the record and the errors.
var failureCallback = function(task) {
console.log( task.name );
console.log( task.errors );
console.log( "You have " + task.errors.length + " errors." );
}
Channel Support
Keep your users up to date without waiting for them to refresh the page. Subscribe them to a channel and update it from wherever you please.
Tune in on the client side.
channel = dispatcher.subscribe('posts');
channel.bind('new', function(post) {
console.log('a new post about '+post.title+' arrived!');
});
Broadcast to the channel from anywhere inside your Rails application. An existing controller, a model, a background job, or a new WebsocketRails controller.
latest_post = Post.latest
WebsocketRails[:posts].trigger 'new', latest_post
Private Channel Support
Need to restrict access to a particular channel? No problem. We've got that.
Private channels give you the ability to authorize a user's subscription using the authorization mechanism of your choice.
Just tell WebsocketRails which channels you would like to make private and how you want to handle channel authorization in the
event router by subscribing to the websocket_rails.subscribe_private
event.
WebsocketRails::EventMap.describe do
private_channel :secret_posts
namespace :websocket_rails
subscribe :subscribe_private, :to => AuthenticationController, :with_method => :authorize_channels
end
Or you can always mark any channel as private later on.
WebsocketRails[:secret_posts].make_private
On the client side, you can use the dispatcher.subscribe_private()
method to subscribe to a private channel.
Read the Private Channel Wiki for more information on dealing with private channels.
Development
This gem is created and maintained by Dan Knox and Kyle Whalen under the MIT License.
Brought to you by:
Three Dot Loft LLC