Transmission_API.markdown
NOTE
This tutorial is slightly out of date. Rocket now includes slightly more code in a freshly created application. I'll rewrite this, and probably re-record the screencast soon to reflect these changes. The change is very small, and this example will still work. The only difference is that new apps now include a starting view and have a single line of code added to the public/app.js to make that view visible by default.
One of the most important differences between Rocket and other frameworks is the API for calling remote code from the client or server. Rocket gives you a set of Ruby controllers on the server, and Javascript controllers on the client. Client controllers can call server controllers, and vice versa. Let's look at some examples.
Our directory structure looks like this:
-
app
-
controllers
-
example.rb
-
example.js
-
-
views
-
example.jade
-
-
-
public
-
html
-
index.html
-
-
javascripts
-
app.js
-
formtacular.js
-
jade.js
-
jquery.js
-
rocket.js
-
rocket_controllers.js
-
rocket_templates.js
-
rocket_utils.js
-
-
public/html/index.html
<html> <head><title>Example App</title>
<script type='text/javascript' src='javascripts/jade'/></script>
<script type='text/javascript' src='javascripts/jquery'/></script>
<script type='text/javascript' src='javascripts/formtacular'/></script>
<script type='text/javascript' src='javascripts/rocket_utils'/></script>
<script type='text/javascript' src='javascripts/rocket_controllers.js'/></script>
<script type='text/javascript' src='javascripts/rocket_templates.js'/></script>
<script type='text/javascript' src='javascripts/app.js'/></script>
<script type='text/javascript' src='javascripts/rocket.js'/></script>
<body> </body></html>This is actually the default content of this file. We merely show it here so you can see that the static HTML page is only used to bootstrap the framework by loading the necessary Javascript files.
public/javascripts/app.js
// Set up empty callbacks for the user to override.Rocket = {}
// Called whenever the user connects (Not just the first time)Rocket.onopen = function() {
}// Called when a user connection is terminatedRocket.onclose = function() {
}// Called whenever the user receives a message from the serverRocket.onmessage = function() {
}// Called when the user first connects to the web socket serverRocket.first_connect = function() {
$("body").html(templates.example.index())
}This file is meant to be modified by the user to get your custom code bootstrapped. In this case, we just need to load a template into the body of the page when the user first connects to the web socket server.
app/views/example/index.jade
!= link_to("O hai, server!", {"Example.say_hello": {name: "actsasbuffoon"}})
This is the template that gets loaded. The only content is a link that will call a server action. Notice that link_to is quite similar to the link_to helper in Rails. The first argument is the link text, the second is the server action and any arguments you'd like to pass, and there is an optional third parameter for various options like a class to attach to the link.
The last argument to link_to is an example of the transmission API. The API is the same on both the client and server, so you don't need to learn two different ways to send data.
Let's examine the argument:
{"Example.say_hello": {
name: "actsasbuffoon"
}}As you can see, it is a simple hash (or object, to use the Javascript lingo) with a single key/value pair. The key is the server side controller and action taking the following format: "controller.action".
The value is a hash of arguments to pass to the action. They will be made available to the controller as the params hash.
To put it all together, the code above will call the say_hello action on the server side ExampleController and pass the following params: {name: "actsasbuffoon"}
Pretty simple, right?
app/controllers/example.rb
class ExampleController
bolt Rocket::Controller
define_action :say_hello do
current_user.transmit({"Example.be_greeted" => {message: "Howdy, #{params["name"]}!"}})
endendThis is our server side controller. There is one action on the controller called say_hello, which transmits a bit of JSON back to the user.
params works pretty much just like it does in Rails. It is a combination of the variables explicitly passed as arguments to the action, as well as any form values.
current_user.transmit is how we send data back to the user. It follows the same transmission rules as the client. This particular code will call the be_greeted action on the client side ExampleController, passing along {message: "Howdy, #{params[:name]}"}.
app/controllers/example.js
ExampleController = function() {
this.be_greeted = function(args) {
alert(args.message)
}}This is the client side controller. It has a single action called be_greeted that will create a message box with the contents of the args["message"] variable. Looking at the server side controller in the last section, we can see the message will be "Howdy, #{params[:name]}!".
Summary
So this simple app create a single button that calls the server side ExampleController.say_hello passing along {name: "actsasbuffoon"}. The controller will call the client ExampleController.be_greeted passing along {message: "Howdy, actsasbuffoon!"}. The client action will then create a message box with "Howdy, actsasbuffoon!" inside.
This example is obviously very contrived, and more than a little complicated to set up something so simple. However, hopefully this gives you some idea of how to pass information from the client to the server and vice/versa.