Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #2 from lifo/master

Updated for the latest Cramp
  • Loading branch information...
commit da8ee715aed9b8569830bf40681f61f582243e11 2 parents d9e845a + 30a60ef
@akitaonrails authored
View
14 Gemfile
@@ -1,11 +1,9 @@
-source 'http://rubygems.org'
+source :rubygems
-gem 'cramp', '~> 0.12'
-gem 'tramp', '~> 0.1'
+gem 'cramp', '~> 0.14.1'
+gem 'thin'
-gem 'activesupport', '3.0.4'
-gem 'rack', '~> 1.2.1'
-gem 'eventmachine', '~> 0.12.10'
+gem 'http_router'
-gem 'usher', '~> 0.8.3'
-gem 'thin', '~> 1.2.7'
+gem 'mysql2', '~> 0.2.11'
+gem 'activerecord'
View
62 Gemfile.lock
@@ -1,44 +1,46 @@
GEM
remote: http://rubygems.org/
specs:
- activemodel (3.0.4)
- activesupport (= 3.0.4)
+ activemodel (3.0.9)
+ activesupport (= 3.0.9)
builder (~> 2.1.2)
- i18n (~> 0.4)
- activesupport (3.0.4)
- arel (0.4.0)
- activesupport (>= 3.0.0.beta)
+ i18n (~> 0.5.0)
+ activerecord (3.0.9)
+ activemodel (= 3.0.9)
+ activesupport (= 3.0.9)
+ arel (~> 2.0.10)
+ tzinfo (~> 0.3.23)
+ activesupport (3.0.9)
+ arel (2.0.10)
builder (2.1.2)
- cramp (0.12)
- activesupport (~> 3.0.4)
- eventmachine (~> 0.12.10)
- rack (~> 1.2.1)
- daemons (1.1.0)
- eventmachine (0.12.10)
- fuzzyhash (0.0.11)
+ cramp (0.14.1)
+ activesupport (~> 3.0.9)
+ eventmachine (~> 1.0.0.beta.3)
+ rack (~> 1.3.2)
+ thor (~> 0.14.6)
+ daemons (1.1.4)
+ eventmachine (1.0.0.beta.3)
+ http_router (0.10.1)
+ rack (>= 1.0.0)
+ url_mount (~> 0.2.1)
i18n (0.5.0)
- mysqlplus (0.1.2)
- rack (1.2.1)
- thin (1.2.7)
+ mysql2 (0.2.11)
+ rack (1.3.2)
+ thin (1.2.11)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
- tramp (0.1)
- activemodel (~> 3.0.0.beta4)
- activesupport (~> 3.0.0.beta4)
- arel (~> 0.4.0)
- mysqlplus (~> 0.1.1)
- usher (0.8.3)
- fuzzyhash (>= 0.0.11)
+ thor (0.14.6)
+ tzinfo (0.3.29)
+ url_mount (0.2.1)
+ rack
PLATFORMS
ruby
DEPENDENCIES
- activesupport (= 3.0.4)
- cramp (~> 0.12)
- eventmachine (~> 0.12.10)
- rack (~> 1.2.1)
- thin (~> 1.2.7)
- tramp (~> 0.1)
- usher (~> 0.8.3)
+ activerecord
+ cramp (~> 0.14.1)
+ http_router
+ mysql2 (~> 0.2.11)
+ thin
View
6 README.textile
@@ -1,6 +1,6 @@
h2. Cramp Chat Demo
-"Cramp":http://m.onkey.org/2010/1/7/introducing-cramp is an asynchronous web framework still under development by "Pratik Naik":http://m.onkey.org/ which shows great promise for its use of "EventMachine":http://rubyeventmachine.com/.
+"Cramp":http://cramp.in is an asynchronous web framework still under development by "Pratik Naik":http://m.onkey.org/ which shows great promise for its use of "EventMachine":http://rubyeventmachine.com/.
This is just a proof-of-concept app to showcase Cramp's potential.
@@ -24,7 +24,7 @@ If you want to test the WebSocket implementation outside of Google Chrome 4+, th
It has to be @sudo@ because 843 is a privileged port. Now you need to start up the application itself:
<pre>
- ruby chatserver.rb
+ bundle exec thin --timeout 0 -V -R config.ru start
</pre>
It will start the server on the port 3000. So you can fire up a webbrowser and use either of these URLs:
@@ -51,7 +51,6 @@ h2. Known Issues
* In Firefox and Safari, I had the web-socket.js working properly, but for some reason it stopped working. Beware of flash blockers in your browser.
* In the Polling version it is manually setting the last message's timestamp in the URL. I was still now able to make a version using a Rack::Session
* Just because it is a proof-of-concept, it uses Rack::Static to serve the HTML and JS files, but it's not certain that this is the best way to do it
-* Up until Cramp 0.9, it depends on ActiveRecord, take a look at @lib/fixes.rb@
h2. TODO
@@ -61,6 +60,7 @@ h2. TODO
h2. Changelog
+* 02/14/2011 - Updated to Cramp 0.14.1 and Active Record + Ruby 1.9 + Fibers.
* 02/14/2011 - Updated to Cramp 0.12 and the new Tramp gem.
h2. Credits
View
4 app/controllers/application_controller.rb
@@ -1,7 +1,11 @@
class ApplicationController < Cramp::Action
+ use_fiber_pool
+
include ApplicationHelper
end
class WebSocketApplicationController < Cramp::Websocket
+ use_fiber_pool
+
include ApplicationHelper
end
View
25 app/controllers/chat_controller.rb
@@ -1,15 +1,15 @@
class ChatController < WebSocketApplicationController
- periodic_timer :retrieve_messages, :every => 2
+ periodic_timer :retrieve_messages, :every => 0.1
on_data :receive_message
def retrieve_messages
- @last_message ||= (Time.now - 1.minute)
- Chat.recent(@last_message).all do |messages|
+ messages = @last_message_id ? Chat.since(@last_message_id) : Chat.recent
+
+ if messages.any?
+ @last_message_id = messages.last.id
+
list = messages.map { |msg| { "from" => msg.name, "msg" => msg.message, "sent" => msg.sent_at.to_formatted_s(:short) } }
- if list.size > 0
- @last_message = messages.first.try(:sent_at) || @last_message
- render list.to_json
- end
+ render list.to_json
end
end
@@ -20,12 +20,11 @@ def receive_message(data)
:sent_at => Time.now,
:message => params["msg"]
- chat.save do |status|
- if status.success?
- render formatted_msg("Message Successfully Received.")
- else
- render formatted_msg("Error receiving message: #{status.inspect}.")
- end
+ if chat.save
+ render formatted_msg("Message Successfully Received.")
+ else
+ render formatted_msg("Error receiving message: #{status.inspect}.")
end
end
+
end
View
14 app/controllers/receive_controller.rb
@@ -12,13 +12,13 @@ def receive_message
:sent_at => Time.now,
:message => @params["msg"]
- chat.save do |status|
- if status.success?
- render formatted_msg("Message Successfully Received.")
- else
- render formatted_msg("Error receiving message: #{status.inspect}.")
- end
- finish
+ if chat.save
+ render formatted_msg("Message Successfully Received.")
+ else
+ render formatted_msg("Error receiving message: #{status.inspect}.")
end
+
+ finish
+
end
end
View
20 app/controllers/retrieve_controller.rb
@@ -3,20 +3,22 @@ class RetrieveController < ApplicationController
on_start :retrieve_messages
def check_last_timestamp
- @last_message = Time.parse(request.params["last_timestamp"]) rescue nil
+
yield
end
def retrieve_messages
- @last_message ||= (Time.now - 30.seconds)
- Chat.recent(@last_message).all do |messages|
- list = messages.map { |msg| { "from" => msg.name, "msg" => msg.message, "sent" => msg.sent_at.to_formatted_s(:short), "timestamp" => msg.sent_at } }
- if list.size > 0
- @last_message = messages.first.try(:sent_at) || @last_message
- render list.to_json
- end
- finish
+ @last_message_id = request.params["last_id"]
+ messages = @last_message_id ? Chat.since(@last_message_id) : Chat.recent
+
+ if messages.any?
+ @last_message_id = messages.last.id
+
+ list = messages.map { |msg| { "from" => msg.name, "msg" => msg.message, "sent" => msg.sent_at.to_formatted_s(:short), "id" => msg.id } }
+ render list.to_json
end
+
+ finish
end
end
View
26 app/models/chat.rb
@@ -1,21 +1,11 @@
-class Chat < Tramp::Base
- attribute :id, :type => Integer, :primary_key => true
- attribute :name
- attribute :sent_at
- attribute :message
-
- def sent_at
- Time.parse(read_attribute(:sent_at))
- end
-
- def sent_at=(value)
- write_attribute(:sent_at, value.to_formatted_s(:db))
+class Chat < ActiveRecord::Base
+ validates_presence_of :name
+
+ def self.since(last_id)
+ order('id ASC').where('id > ?', last_id)
end
-
- def self.recent(last_message)
- where(Chat[:sent_at].gt(last_message.to_formatted_s(:db))).
- order(Chat[:sent_at].asc)
+
+ def self.recent(limit = 10)
+ order('id ASC').limit(limit)
end
-
- validates_presence_of :name
end
View
2  app/views/chat.erb
@@ -22,7 +22,7 @@
</li>
<li id="message">
<label for="msg">Message:</label>
- <textarea id='msg' name="msg" rows="3" cols="50"></textarea>
+ <input type='text' id='msg' name="msg" size="50"></input>
</li>
<li id="button">
<input type="submit" value="Say it" id="send"/>
View
8 app/views/chat_poll.erb
@@ -27,14 +27,14 @@
<form id="chat-form" onsubmit="onSubmit(); return false;">
<div><label for="from">Nick:</label> <input id='from' type="text" name="from" value="Foo"/></div>
<div><label for="msg">Message:</label></div>
- <div><textarea id='msg' name="msg" rows="3" cols="50"></textarea></div>
+ <div><input type='text' id='msg' name="msg" size="50"></input></div>
<div><input type="submit" value="Say it" id="submit"/></div>
</form>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
- var lastTimestamp = {};
+ var lastMessage = {};
// method used to update element html
$(document).ready(function() {
@@ -43,12 +43,12 @@
$.ajax({
url: "http://<%= request.host_with_port %>/retrieve",
type: "GET",
- data: lastTimestamp,
+ data: lastMessage,
dataType: "json",
success: function(data) {
$.each(data, function(i, item) {
$("#messages").append( "<div><span class=\"from\">" + item.from + ":</span>\n<span class=\"msg\">" + item.msg + "</span></div>");
- lastTimestamp = { last_timestamp: item.timestamp }
+ lastMessage = { last_id: item.id }
});
scrollDown();
},
View
17 chatserver.rb → config.ru
@@ -2,10 +2,10 @@
require 'bundler'
Bundler.setup(:default)
-require 'usher'
-require 'thin'
+require 'http_router'
require 'cramp'
-require 'tramp'
+require 'active_record'
+
require 'active_support/all'
require 'active_support/json'
@@ -17,9 +17,12 @@
require './app/controllers/receive_controller'
require './app/controllers/static_controller'
require './app/models/chat'
-require './lib/fixes'
-Tramp.init(YAML.load(File.read('./config/database.yml')))
+db_config = YAML.load(File.read('./config/database.yml')).with_indifferent_access
+ActiveRecord::Base.configurations = db_config
+ActiveRecord::Base.establish_connection(ENV['RACK_ENV'] || 'development')
+
Cramp::Websocket.backend = :thin
-Thin::Logging.trace = true
-Rack::Handler::Thin.run app_routes, :Port => 3000
+
+# bundle exec thin --timeout 0 -V -R config.ru start
+run app_routes
View
10 config/database.yml
@@ -1,4 +1,6 @@
----
-:database: cramp_chat_development
-:username: root
-:password: root
+development:
+ adapter: em_mysql2
+ database: cramp_chat_development
+ host: localhost
+ username: root
+ pool: 100
View
4 config/routes.rb
@@ -2,7 +2,7 @@ def app_routes
Rack::Builder.new do
use Rack::Session::Cookie
- routes = Usher::Interface.for(:rack) do
+ routes = HttpRouter.new do
get('/websocket').to(ChatController)
get('/retrieve').to(RetrieveController)
post('/receive').to(ReceiveController)
@@ -13,4 +13,4 @@ def app_routes
run Rack::Cascade.new([file_server, routes])
end
-end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.