-->

How can I pass data to websocket-rack from a class

2019-07-07 20:08发布

问题:

I've got a working configuration of websocket-rack in a sinatra app that is intended for a physical installation with multiple screens. There is functionality working where messages are getting passed back and forth through the websockets just fine.

My problem is this: I have one page with a standard web form (i.e. not a websocket form), and my goal is to collect the params from that form, turn the params into a string variable, then send the contents of that variable (a string) to a different page/screen through a websocket. For the life of me, I can't figure out how to do what should be a relatively simple task, because from the main class in my app, I can't communicate with my Socket class, which from what i understand is basically a rack app.

I tried to resolve it by setting up resque as a middle-man, but quickly discovered that my problem hadn't changed. I can't figure out how to call a method and/or pass a variable to the Socket from another class so that it will push to the browser.

Basically, I have an app.rb that is like this:

    module SomeThing
      class App < Sinatra::Base
        get '/' do
          #show a form
        end

        post '/submit' do
          #receive params
          #save params
          new_message = params.inspect
          #dream up some way to pass new_message to websocket
        end

        post '/otherscreen' do
          #have an open websocket to receive new_message
        end
      end


      class Socket < Rack::WebSocket::Application

        def on_open(env)
          puts "Client connected"
          send_data "Oh hai!"
        end

        def on_close(env)
          puts "Client disconnected"
        end

        def on_message(env, msg)
           puts "Received message from client: " + msg
        end

        def on_error(env, error)
          puts "An error occured: " + error.message
        end

        def pass_message(env, new_message)
          send_data new_message
        end
      end   
    end

Please let me know if you need more info to solve this. I'm happy to provide whatever is needed, just unsure what that might be right now.

Do you know how I can resolve this? It's killing me.

Thanks ahead of time!

回答1:

So, I wrote to the author of websocket-rack, Bernard Potocki, and he said this:

"What I usually do is save list of active connections to some kind of class variable. One of possible implementations might look like in this gist: https://gist.github.com/imanel/a00d6b65561ebba43b9a "

Contents of gist, in case it gets removed:

class Socket < Rack::WebSocket::Application

  def self.connections
    @connections ||= []
  end

  def self.send_to_all(message)
    @connections.each {|connection| connection.send_data(message)
  end

  def on_open(env)
    self.class.connections << self
  end

  def on_close(env)
    self.class.connection.delete(self)
  end

end

Ultimately, however, I did not test this solution as we were able to resolve this issue using Redis and Event Machine, so be aware that that is an option as well.