diff --git a/app/controllers/socket_controller.rb b/app/controllers/socket_controller.rb new file mode 100644 index 000000000..6046697b7 --- /dev/null +++ b/app/controllers/socket_controller.rb @@ -0,0 +1,31 @@ +class SocketController < ApplicationController + include ApplicationHelper + include SocketHelper + include Rails.application.routes.url_helpers + before_filter :authenticate_user! + + + + # def default_url_options() + # {:host=> 'example.com'} + # end + + def incoming(msg) + puts "#{msg} connected!" + end + + def new_subscriber + WebSocket.subscribe + end + + def outgoing(object) + @_request = ActionDispatch::Request.new({}) + WebSocket.push_to_clients(action_hash(object)) + end + + def delete_subscriber(sid) + WebSocket.unsubscribe(sid) + end + + +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index eb6a95578..91c199c97 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,4 +4,8 @@ class UsersController < ApplicationController def index @users = User.sort(:created_at.desc).all end + + def show + @user = User.find(params[:id]) + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index dbceffe78..c476210ab 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -38,8 +38,8 @@ module ApplicationHelper end def owner_picture - default = "#{root_url}images/user/default.jpg" - image = "#{root_url}images/user/#{User.first.profile.last_name.gsub(/ /,'').downcase}.jpg" + default = "/images/user/default.jpg" + image = "/images/user/#{User.first.profile.last_name.gsub(/ /,'').downcase}.jpg" if File.exist?("public/images/user/#{User.first.profile.last_name.gsub(/ /,'').downcase}.jpg") image_tag image, :id => "user_picture" diff --git a/app/helpers/socket_helper.rb b/app/helpers/socket_helper.rb new file mode 100644 index 000000000..36124a60d --- /dev/null +++ b/app/helpers/socket_helper.rb @@ -0,0 +1,26 @@ +module SocketHelper + include ApplicationHelper + + def obj_id(object) + (object.is_a? Post) ? object.id : object.post_id + end + + def url_options + {:host => ""} + end + + def action_hash(object) + begin + v = render_to_string(:partial => type_partial(object), :locals => {:post => object}) unless object.is_a? Retraction + rescue Exception => e + puts "web socket view rendering failed for some reason." + v.inspect + puts object.inspect + puts e.message + raise e + end + {:class =>object.class.to_s.underscore.pluralize, :html => v, :post_id => obj_id(object)}.to_json + end + + + +end diff --git a/app/models/comment.rb b/app/models/comment.rb index bcc3c929b..55cfe7890 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -36,6 +36,6 @@ class Comment def send_to_view - WebSocket.update_clients(self) + SocketController.new.outgoing(self) end end diff --git a/app/models/post.rb b/app/models/post.rb index 22ebc7859..266e16d0b 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -53,11 +53,11 @@ class Post end def send_to_view - WebSocket.update_clients(self) + SocketController.new.outgoing(self) end def remove_from_view - WebSocket.update_clients(Retraction.for(self)) + SocketController.new.outgoing(Retraction.for(self)) end end diff --git a/app/views/js/_websocket_js.haml b/app/views/js/_websocket_js.haml index 93286423c..a4ec035e2 100644 --- a/app/views/js/_websocket_js.haml +++ b/app/views/js/_websocket_js.haml @@ -8,7 +8,7 @@ function debug(str){ $("#debug").append("
" + str); }; ws = new WebSocket("ws://#{request.host}:8080/"); - ws.onmessage = function(evt) { + ws.onmessage = function(evt) { var obj = jQuery.parseJSON(evt.data); debug("got a " + obj['class']); diff --git a/app/views/status_messages/_status_message.html.haml b/app/views/status_messages/_status_message.html.haml index f3e94c09d..1333640f9 100644 --- a/app/views/status_messages/_status_message.html.haml +++ b/app/views/status_messages/_status_message.html.haml @@ -1,14 +1,14 @@ %li.message{:id => post.id, :class => ("mine" if mine?(post))} %span.from - = link_to_person post.person + = link_to post.person.real_name, post.person = auto_link post.message %div.time = link_to(how_long_ago(post), status_message_path(post)) \-- = link_to "show comments (#{post.comments.count})", '#', :class => "show_post_comments" - = render "comments/comments", :post => post + = render "comments/comments", :post => post - if mine?(post) .destroy_link - = link_to 'Delete', status_message_path(post), :confirm => 'Are you sure?', :method => :delete, :remote => true + = link_to 'Delete', status_message_url(post), :confirm => 'Are you sure?', :method => :delete, :remote => true diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index dded445cc..bf760d087 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -7,5 +7,5 @@ # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) - inflect.uncountable %w(dashboard) + inflect.uncountable %w(dashboard socket) end diff --git a/config/initializers/socket.rb b/config/initializers/socket.rb index 105314b8a..d1fcfc315 100644 --- a/config/initializers/socket.rb +++ b/config/initializers/socket.rb @@ -1,31 +1,43 @@ require 'em-websocket' require 'eventmachine' -require 'lib/socket_render' + + + module WebSocket EM.next_tick { - EM.add_timer(0.1) do - @channel = EM::Channel.new - puts @channel.inspect - include SocketRenderer - - SocketRenderer.instantiate_view - end + initialize_channel EventMachine::WebSocket.start( :host => "0.0.0.0", :port => APP_CONFIG[:socket_port], :debug =>APP_CONFIG[:debug]) do |ws| ws.onopen { - sid = @channel.subscribe { |msg| ws.send msg } + @ws = ws + sid = SocketController.new.new_subscriber - ws.onmessage { |msg| }#@channel.push msg; puts msg} + ws.onmessage { |msg| SocketController.new.incoming(msg) }#@channel.push msg; puts msg} - ws.onclose { @channel.unsubscribe(sid) } + ws.onclose { SocketController.new.delete_subscriber(sid) } } end } - def self.update_clients(object) - @channel.push(SocketRenderer.view_hash(object).to_json) if @channel + def self.initialize_channel + @channel = EM::Channel.new end + + def self.push_to_clients(html) + @channel.push(html) + end + + def self.unsubscribe(sid) + @channel.unsubscribe(sid) + end + + + def self.subscribe + @channel.subscribe{ |msg| @ws.send msg } + end + end + diff --git a/lib/socket_render.rb b/lib/socket_render.rb deleted file mode 100644 index 8d77f4c6a..000000000 --- a/lib/socket_render.rb +++ /dev/null @@ -1,40 +0,0 @@ -module SocketRenderer - require 'app/helpers/application_helper' - def self.instantiate_view - @view = ActionView::Base.new(ActionController::Base.view_paths, {}) - class << @view - include ApplicationHelper - include Rails.application.routes.url_helpers - include ActionController::RequestForgeryProtection::ClassMethods - def protect_against_forgery? - false - end - end - end - - def self.view_hash(object) - begin - v = view_for(object) unless object.is_a? Retraction - - rescue Exception => e - puts "in failzord " + v.inspect - puts object.inspect - puts e.message - raise e - end - - {:class =>object.class.to_s.underscore.pluralize, :html => v, :post_id => obj_id(object)} - end - - def self.view_for(object) - @view.render @view.type_partial(object), :post => object - end - - def self.obj_id(object) - if object.is_a? Post - object.id - else - object.post_id - end - end -end diff --git a/spec/controllers/socket_controller_spec.rb b/spec/controllers/socket_controller_spec.rb new file mode 100644 index 000000000..5f5a8b70f --- /dev/null +++ b/spec/controllers/socket_controller_spec.rb @@ -0,0 +1,40 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +describe 'SocketController' do + render_views + before do + @user = Factory.create(:user) + SocketController.unstub!(:new) + #EventMachine::WebSocket.stub!(:start) + @controller = SocketController.new + stub_socket_controller + end + + it 'should unstub the websocket' do + WebSocket.initialize_channel + @controller.class.should == SocketController + end + + it 'should add a new subscriber to the websocket channel' do + WebSocket.initialize_channel + @controller.new_subscriber.should == 1 + end + describe 'actionhash' do + before do + @message = Factory.create(:status_message, :person => @user) + end + + it 'should actionhash posts' do + json = @controller.action_hash(@message) + json.include?(@message.message).should be_true + json.include?('status_message').should be_true + end + + it 'should actionhash retractions' do + retraction = Retraction.for @message + json = @controller.action_hash(retraction) + json.include?('retraction').should be_true + json.include?("html\":null").should be_true + end + end +end diff --git a/spec/factories.rb b/spec/factories.rb index b208bc056..925f7c5be 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -19,6 +19,7 @@ Factory.define :user do |u| u.sequence(:email) {|n| "bob#{n}@aol.com"} u.password "bluepin7" u.password_confirmation "bluepin7" + u.url "www.example.com" u.profile Profile.new( :first_name => "Bob", :last_name => "Smith" ) end diff --git a/spec/helpers/socket_helper_spec.rb b/spec/helpers/socket_helper_spec.rb new file mode 100644 index 000000000..45c77f564 --- /dev/null +++ b/spec/helpers/socket_helper_spec.rb @@ -0,0 +1,4 @@ +require File.dirname(__FILE__) + '/../spec_helper' +describe SocketHelper do + +end diff --git a/spec/lib/message_handler_spec.rb b/spec/lib/message_handler_spec.rb index ffb4b078c..88eda43de 100644 --- a/spec/lib/message_handler_spec.rb +++ b/spec/lib/message_handler_spec.rb @@ -5,6 +5,7 @@ describe MessageHandler do @handler = MessageHandler.instance @message_body = "I want to pump you up" @message_urls = ["http://www.google.com/", "http://yahoo.com/", "http://foo.com/"] + end after do diff --git a/spec/lib/socket_renderer_spec.rb b/spec/lib/socket_renderer_spec.rb index 0b3e48505..009de8b78 100644 --- a/spec/lib/socket_renderer_spec.rb +++ b/spec/lib/socket_renderer_spec.rb @@ -1,4 +1,5 @@ -require File.dirname(__FILE__) + '/../spec_helper' +=begin + require File.dirname(__FILE__) + '/../spec_helper' describe SocketRenderer do before do @@ -20,3 +21,4 @@ describe SocketRenderer do hash[:class].should == "status_messages" end end +=end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a72af5197..a4d470af2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,7 +24,7 @@ RSpec.configure do |config| config.before(:each) do DatabaseCleaner.start - #WebSocket.stub!(:update_clients) + stub_socket_controller end config.after(:each) do @@ -32,3 +32,11 @@ RSpec.configure do |config| end end + def stub_socket_controller + mock_socket_controller = mock('socket mock') + mock_socket_controller.stub!(:incoming).and_return(true) + mock_socket_controller.stub!(:new_subscriber).and_return(true) + mock_socket_controller.stub!(:outgoing).and_return(true) + mock_socket_controller.stub!(:delete_subscriber).and_return(true) + SocketController.stub!(:new).and_return(mock_socket_controller) + end