-
Notifications
You must be signed in to change notification settings - Fork 284
WebsocketRails Controllers
Similar to standard Rails requests, each event processed by the server is handled by a fresh instance of your controller object. Any instance variables set in your controller will be wiped out after the action for an event finishes processing. This works great in the standard Rails request/response cycle. However, it is not always convenient for dealing with long running persistent connections such as WebSocket clients. Because of this, we provide our own Controller DataStore object, accessible in a WebsocketRails controller, to make it easier to temporarily store data between events. This is explained further in the DataStore Wiki.
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. Values added to the
controller data store from inside 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
controller_store[:message_count] = 0
end
end
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'
});
If the current event was triggered by the client with success and
failure callbacks attached, you can execute them from your controller
action using the trigger_success
and trigger_failure
methods.
Both methods can take an optional object that will be passed to the callback functions on the client.
def awesomeness_approval
if message[:awesomeness] > 5
trigger_success {:message => 'awesome level is sufficient'}
else
trigger_failure {:message => 'awesome level is insufficient'}
end
end
Now you can trigger the awesomeness_approval
event on the
JavaScript client and easily handle the result.
var success = function(response) {
console.log("You are awesome because: "+response.message);
}
var failure = function(response) {
console.log("You are not very awesome because: "+response.message);
}
var message = { awesomeness: 4 }
dispatcher.trigger('awesomeness_approval', message, success, failure);
You can send an event to a specific client using the UserManager
which can be accessed via WebsocketRails.users
.
WebsocketRails.users[myUser.id].send_message('new_notification', {:message => 'you\'ve got an upvote '})
Note: you can use this method outside the websocket controller too.
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
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 callbacks are similar to the before_filter/after_filter/around_filter
(and in Rails 4 before_action/after_action/around_action
) methods in Rails. You can attach a block of code to be run when a particular event is triggered within a controller or when any action inside the controller is called.
The following callback will be called any time the new_event
event is triggered:
class EventController < WebsocketRails::BaseController
before_filter :only => :new_event do
puts "new_event was called"
end
def new_event
# handle event
end
end
If you want to execute a block before any action in the controller is called regardless of the event, just leave off any arguments.
class EventController < WebsocketRails::BaseController
before_filter do
puts "an event handled by this controller was called"
end
end
And come more examples:
class EventController < WebsocketRails::BaseController
before_filter :ensure_logged_in!
after_filter do
puts "perform post-action work"
end
around_filter :time_request
def ensure_logged_in!
if current_user.nil?
current_user = User.new
end
end
def time_request
start = Time.now
yield
delta = Time.now - start
puts "Action took #{delta.to_f} seconds"
end
end
Callbacks will be executed in the same order as they are subscribed.
Please see Rails documentation of Filters for more examples.
You can use all of the standard Rails controller helper methods such as url_for
inside of a WebsocketRails Controller. You can also use controller helper methods provided by gems like Devise.