Skip to content

Instantly share code, notes, and snippets.

@rkh
Created December 14, 2011 12:55
Show Gist options
  • Save rkh/1476463 to your computer and use it in GitHub Desktop.
Save rkh/1476463 to your computer and use it in GitHub Desktop.
Simple Chat Application using the Sinatra Streaming API
# coding: utf-8
require 'sinatra'
set server: 'thin', connections: []
get '/' do
halt erb(:login) unless params[:user]
erb :chat, locals: { user: params[:user].gsub(/\W/, '') }
end
get '/stream', provides: 'text/event-stream' do
stream :keep_open do |out|
settings.connections << out
out.callback { settings.connections.delete(out) }
end
end
post '/' do
settings.connections.each { |out| out << "data: #{params[:msg]}\n\n" }
204 # response without entity body
end
__END__
@@ layout
<html>
<head>
<title>Super Simple Chat with Sinatra</title>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body><%= yield %></body>
</html>
@@ login
<form action='/'>
<label for='user'>User Name:</label>
<input name='user' value='' />
<input type='submit' value="GO!" />
</form>
@@ chat
<pre id='chat'></pre>
<script>
// reading
var es = new EventSource('/stream');
es.onmessage = function(e) { $('#chat').append(e.data + "\n") };
// writing
$("form").live("submit", function(e) {
$.post('/', {msg: "<%= user %>: " + $('#msg').val()});
$('#msg').val(''); $('#msg').focus();
e.preventDefault();
});
</script>
<form>
<input id='msg' placeholder='type message here...' />
</form>
@baronlinden
Copy link

It seems like it has to do with the fact that I have mounted the Sinatra app inside a Rails app. I get it to work when running the Sinatra app by itself, but when running it inside the Rails app the connection seems to be dropped because the browser is reconnecting continuously and therefore I won't be able to stream messages from my message handler.

Is there anything I need to configure in Rails for this to work?

@rkh
Copy link
Author

rkh commented Feb 15, 2012

The Rails issue is well known, dunno what's breaking here, I think they wrap the body object somewhere and the errback/callback methods get lost on the way. Solution for now is to mount it in the config.ru rather than your routes.rb.

@baronlinden
Copy link

Yeah, I tried adding the Sinatra app as a Rails middleware and it worked. Cheers.

@patrickpang
Copy link

pretty good.
a nice alternative with websockets, with javascript polyfills

@celeryclub
Copy link

Just what I needed! Thanks a lot.

@mig-hub
Copy link

mig-hub commented May 23, 2013

Nice,

Since no specific version of jQuery is requested, it doesn't work anymore on the Heroku demo.
Because "live" was removed.
It works with this revision

You probably knew this as it was a year ago, but just in case...

@akemrir
Copy link

akemrir commented Sep 27, 2013

rkj, do you have padrino version?

@mcfiredrill
Copy link

How many clients would this reasonable support, using say, thin?

@multiholle
Copy link

Change line 29 to <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script> if you have trouble getting it to run. There was an api change in JQuery 1.9.

@flibbles
Copy link

As @multiholle pointed out, JQuery changed.

If you want to use the latest version of jquery, the line:

$("form").live("submit", function(e) {

can be changed to:

$("body").on("submit", "form", function(e) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment