Skip to content

WebsocketRails Controllers

DanKnox edited this page Jul 4, 2012 · 13 revisions

There are a few differences between WebSocket controllers and standard Rails controllers. The biggest of which, is that each event will be handled by the same, continually running instance of your controller class. This means that if you set any instance variables in your methods, they will still be available when the next event is processed. On top of that, every single client that is connected will share these same instance variables. This can be an advantage if used properly, but it can also lead to bugs if not expected. We provide our own DataStore object accessible in a WebsocketRails controller to make it easier to store data isolated from each connected client. This is explained further below.

Initializing the Controller

Do not override the initialize method in your class to set up. Instead, define an initialize_session method and perform your set up there. The initialize_session method will be called the first time a controller is subscribed to an event in the event router. Instance variables defined in the initialize_session method will be available throughout the course of the server lifetime.

class ChatController < WebsocketRails::BaseController
  def initialize_session
    # perform application setup here
    @message_count = 0
  end
end

Triggering Events on the Client

You can trigger an event on the client using the send_message method. The send_message method takes two arguments, the event name to trigger, and an object to send along with the event.

new_message = {:message => 'this is a message'}
send_message :event_name, new_message

You would handle this event on the client side with the following JavaScript (assuming you already have a dispatcher initialized):

dispatcher.bind('event_name', function(data) {
  console.log(data.message) // would output 'this is a message'
});

Broadcasting Events to all Clients

You can trigger events on all connected clients at once using the broadcast_message method. It takes the same arguments as the send_message. If you wish to broadcast to a subset of connected clients, you can use Channels.

new_comment = Comment.latest
broadcast_message :new_comment, new_comment

Triggering Namespaced Events

Namespaced events are triggered from a controller by passing the :namespace option to the send_message or broadcast_message methods.

products = Product.find(:all, :limit => 10)
send_message :new_list, products, :namespace => 'products'

You would bind to this event on the client with the following JavaScript:

dispatcher.bind('products.new_list', function(products) {
  console.log('we just received ' + products.size + ' new products!');
});

Event Observers

Event observers are similar to the before_filter methods in Rails. You can attach a code block to be run when a particular event is triggered within a controller or when any action inside the controller is called.

The following observer will be called any time the new_event event is triggered:

class EventController < WebsocketRails::Base
  observe :new_event do
    puts "new_event was called"
  end
end

If you want to execute a block before any action in the controller is called regardless of the event, just leave off the event name argument.

class EventController < WebsocketRails::Base
  observe do
    puts "an event handled by this controller was called"
  end
end

Observers will be executed in the same order as they are subscribed.

Standard Rails Controller Helpers

You can use all of the standard Rails controller helper methods such as url_for. You can also use controller helper methods provided by gems like Devise.