diff --git a/app/controllers/socket_controller.rb b/app/controllers/socket_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..6046697b73c4757c286f38a6df3d65fe3ef2a7d7 --- /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 eb6a955784e22c5afa5ac0c4b47829194f69f0a4..91c199c97ec2dbbaf7f17adefe47e2304a054c55 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 dbceffe7859e025955175f6672cc47d179c29d61..c476210ab1a1dbb877e3685c61f8d4af1db0e9cd 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 0000000000000000000000000000000000000000..36124a60dacfa161f1c5c4b4de892d15c4bca54c --- /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 bcc3c929b880b77d932a35de89965ff1b58c2aad..55cfe7890de2a42e2f0db220e36943c64c19e2ec 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 22ebc7859480f62e97b7194a1d662230fa8daee1..266e16d0b73ecfede3092e7d755d3787865d3e68 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 93286423cc7e64135551d91c17a750f912adbecd..a4ec035e209762736ae6aca4f0622ef90b65f2f6 100644 --- a/app/views/js/_websocket_js.haml +++ b/app/views/js/_websocket_js.haml @@ -8,7 +8,7 @@ function debug(str){ $("#debug").append("<p>" + 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 f3e94c09d212feeca393f2cb6ca822767e74938a..1333640f9c7f9f90eb6231403afc577b9d0de67d 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 dded445ccbf772673d5b59b7292201762eb53510..bf760d0873157f2a1d240e4d9e0ada1b67b0a887 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 105314b8ae1d2ccdbdcc4d4bb158e4a83976aa95..d1fcfc31595a27db259c6d50b47dff7c778568a9 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 8d77f4c6abf4533d222787e93922173de808d22a..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..5f5a8b70f3836d8a07305d3093fc861e3e323001 --- /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 b208bc056e54982010c5af56c4719d33bb87f965..925f7c5be134c5f065929c4bac8e332698dc0327 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 0000000000000000000000000000000000000000..45c77f56463380f8823b44d7b230462e02a2b599 --- /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 ffb4b078cd3e48fdf89bfd54382157747f3d2cc9..88eda43de7f8ed3506a861a06f8b46e93b2c3073 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 0b3e4850524013aa6bd8331fa652ea772fb27ebd..009de8b78ab416718060708fd1a793c5ff34b145 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 a72af5197dc24dcb6f3cb275964a3d33a2df5ddc..a4d470af2efd151650573182cb51f4ac94a3ae78 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