Skip to content
This repository

Plug and play websocket support for ruby on rails.

Merge pull request #198 from Oxynum/master

Add unbind functions to the Javascript client for the dispatcher and channels
latest commit bbb174cbeb
Dan Knox DanKnox authored April 18, 2014
Octocat-spinner-32 bin Add deprecation notice to thin-socketrails executable. July 17, 2012
Octocat-spinner-32 lib Merge pull request #198 from Oxynum/master April 18, 2014
Octocat-spinner-32 spec add spec for unbind function April 01, 2014
Octocat-spinner-32 .gitignore Refactor *.coffee files. Add reconnect() method. December 01, 2013
Octocat-spinner-32 .rspec Complete rewrite of the ConnectionManager Rack application. May 30, 2012
Octocat-spinner-32 .ruby-version Update to the latest ruby version and fix the jasmine WebSocketRails.… March 14, 2014
Octocat-spinner-32 .travis.yml Update to the latest ruby version and fix the jasmine WebSocketRails.… March 14, 2014
Octocat-spinner-32 CHANGELOG.md Update CHANGELOG and bump version to 0.7.0 for release. March 14, 2014
Octocat-spinner-32 Gemfile Update to the latest ruby version and fix the jasmine WebSocketRails.… March 14, 2014
Octocat-spinner-32 Gemfile.lock Update CHANGELOG and bump version to 0.7.0 for release. March 14, 2014
Octocat-spinner-32 Guardfile Set up Jasmine specs for JavaScript client. July 04, 2012
Octocat-spinner-32 MIT-LICENSE Complete rewrite of the ConnectionManager Rack application. May 30, 2012
Octocat-spinner-32 README.md add some comments and a reference to the unbind function in the README March 23, 2014
Octocat-spinner-32 Rakefile Add jasmine:ci to default rake tasks for testing on Travis. July 04, 2012
Octocat-spinner-32 TODO_LIST.md Bump version for release and update changelog/readme/todo-list. April 28, 2013
Octocat-spinner-32 websocket-rails.gemspec Adds a dependency on Redis-Objects. Fix Channel manager's channel tok… October 27, 2013
README.md

Websocket-Rails

Build Status Gem Version Code Climate

If you haven't done so yet, check out the Project Page to get a feel for the project direction. Feedback is very much appreciated. Post an issue on the issue tracker or shoot us an email to give us your thoughts.

Find us on IRC #websocket-rails

Stop by #websocket-rails on freenode if you would like to chat or have any questions.

Recent Updates

Check out the CHANGELOG to find out what's new.

As of version 0.2.0, non event machine based web servers such as Phusion Passenger are supported through the use of the Standalone Server Mode.

Overview

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 with Flash sockets.

Installation and Usage Guides

Handle Events With Class

Map events to controller actions using an Event Router.

WebsocketRails::EventMap.describe do
  namespace :tasks do

    # using a Hash to specify the target
    subscribe :create, :to => TaskController, :with_method => :create

    # using the same syntax as routes.rb
    subscribe :update, 'task#update'

    # if your controller is not a top-level object
    subscribe :create_admin, :to => Admin::TaskController, :with_method => :create

    subscribe :update_admin, 'admin/task#update'

  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', task, 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." );
}

You can stop listening to an event now by using the unbind function.

dispatcher.unbind('tasks.create_success');

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 by using the private_channel method in the Event Router. Then handle the channel authorization by subscribing to the websocket_rails.subscribe_private event.

WebsocketRails::EventMap.describe do
  private_channel :secret_posts

  namespace :websocket_rails
    subscribe :subscribe_private, :to => AuthorizationController, :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 subscribing to private channels from the JavaScript client and handling the authorization in your controller.

Credit where credit is due

Big thanks to our contributors who have helped keep this project moving.

Special thanks to @nessche who provided the improved routing DSL and RSpec matcher suite.

The websocket-rails organization logo was kindly provided by Uken Games.

Development

Please check out the Development Guide if you are interested in contributing. It should cover everything you need to get up and running.

Core Team

The current websocket-rails core team consists of the following individuals:

New contributors and pull requests are always welcome.

Something went wrong with that request. Please try again.