Installation

  1. Get the plugin from: http://rubyforge.org/frs/?group_id=1884 or alternatively get it from the svn: svn://rubyforge.org//var/svn/juggernaut/trunk/juggernaut and put it in the dir: vendor/plugins
  2. Run: rake install_juggernaut
  3. If you're going to use prototype/scriptaculous then add the default javascripts to your view (not required):
    <%= javascript_include_tag :defaults %>
  4. Add this to your view/layout header
    <%= javascript_include_tag "juggernaut_javascript" %>
  5. Add this to your view/layout body:
    <%= flash_plugin(session[:juggernaut_channels]) %>
  6. Install the Json library (gem install json).
  7. Configure the ports and host. This is very important as flash will only allow you to make a socket connection
  8. to the same host as the address the client is viewing. Configure the ports in config/juggernaut_config.yml.

And you are all set!

Usage

To demonstrate Juggernaut I'll walk you through building a simple chat.

Start the push server going by running:
ruby script/push_server

The chat controller:

def index
session[:juggernaut_channels] = ["chat_channel"]
end

def send_data
input_data = Juggernaut.html_and_string_escape(params[:chat_input])
data = "new Insertion.Top('chat_data','<li>#{input_data}</li>');"
Juggernaut.send(data,session[:juggernaut_channels])
render :nothing => "true"
end
The index.rhtml

<html>
<head>
<%= javascript_include_tag :defaults %>
<%= javascript_include_tag "juggernaut_javascript" %>
</head>
<body>
<%= form_remote_tag(
:url => { :action => :send_data },
:complete => "$('chat_input').value = ''" ) %>
<%= text_field_tag( 'chat_input', '', { :size => 20, :id => 'chat_input'} ) %>
<%= submit_tag "Add" %>
<%= end_form_tag %>
<ul id="chat_data" style="list-style:none">
</ul>
<%= flash_plugin(session[:juggernaut_channels]) %>
</body>
</html>

Start the webserver going with:
ruby script/server

Try it and see what you think. If it doesn't work please visit the faq.
As soon as the page loads the 'flash plugin' opens a socket to the push server and subscribes to the appropriate channels. In this case I'm storing the channels I want to subscribe to in the session. When one client initiates the 'send data' command the javascript is created and sent to the push server with the command Juggernaut.send(data,channels). The push server then broadcasts the message to all clients on the selected channels.

Advanced Usage

Let's take a simple ajaxified rails app with Juggernaut - and then add it.

Controller:

def milestone_create
begin
@milestone = Milestone.new(params[:milestone])
@successful = @milestone.save
rescue
end
end

RJS (view)

if @successful
page.remove "#{@milestone.id}_milestone_view_container"
end

Now the controller with Juggernaut added:

def milestone_create
begin
@milestone = Milestone.new(params[:milestone])
@successful = @milestone.save

partial_to_string = Juggernaut.parse_string(render_to_string(:partial => "milestone"))

Juggernaut.send("
createMilestone('#{partial_to_string}','#{cookies[:_session_id]}')
", session[:juggernaut_channels])

rescue
"alert('Request failed');"
end
end

Add some javascrip to application.js:

function createMilestone(data, ses_id) {
if (getCookie('_session_id') != ses_id) {
new Insertion.Top('milestone_list', data);
}
}

Juggernaut Helpers

As you can see, Juggernaut provides some helper methods to easily parse strings from 'render_to_string' etc.

Juggernaut.parse_string(string)
This takes a string, usually a rendered partial. It then escapes the string, and parses it onto one line so it's understood by JavaScript.

Juggernaut.string_escape(string)
This does exactly what it says on the tin, escapes a string (not url encoding).

Juggernaut.html_escape(string)
Same as the rails helper h().

Juggernaut.html_and_string_escape(string)
Just combines the two methods above - usefull for chats.


n4
Juggernaut for Ruby on Rails initiates a flash xmlsocket between server and browser allowing real time communication between the two. This opens the door to all sorts of functionality such as chats and collaborative wikis/cms. The open socket connection allows the server to 'push' base64 encoded javascript to the browser which is subsequently decoded and evaluated.

delicious digg it