2

I'm trying to make an app that uses ruby on rails for the backedn and reactjs for the frontent. I expect tahat several people will use this app at the same time and the app should work without refreshing the page or redirecting to some new routes (except for signin, signout, signup...). For the communication between backend and frontend I'm trying to use websockets but I get errors in the terminal and in the console of the browser. Both error repeat each second or so.

Error I get in the terminal is:

13:58:00 rails.1   | [ActionCable] [[email protected]] Finished "/cable/" [WebSocket] for 127.0.0.1 at 2017-05-04 13:58:00 +0200
13:58:00 rails.1   | [ActionCable] [[email protected]] There was an exception - NoMethodError(undefined method `fetch' for nil:NilClass)
13:58:00 rails.1   | [ActionCable] [[email protected]] /home/mislav/.rvm/gems/ruby-2.3.0/gems/actioncable-5.0.2/lib/action_cable/server/configuration.rb:25:in `pubsub_adapter'
13:58:00 rails.1   | /home/mislav/.rvm/gems/ruby-2.3.0/gems/actioncable-5.0.2/lib/action_cable/server/base.rb:76:in `block in pubsub'
  ...
# here are now a lot of errors like :
13:58:00 rails.1   | /home/mislav/.rvm/gems/ruby-2.3.0/gems/actioncable-5.0.2/lib/action_cable/channel/streams.rb:106:in `block in stop_all_streams'
13:58:00 rails.1   | /home/mislav/.rvm/gems/ruby-2.3.0/gems/actioncable-5.0.2/lib/action_cable/channel/streams.rb:105:in `each'
13:58:00 rails.1   | /home/mislav/.rvm/gems/ruby-2.3.0/gems/actioncable-5.0.2/lib/action_cable/channel/streams.rb:105:in `stop_all_streams'
  ...
14:01:09 rails.1   | /home/mislav/.rvm/gems/ruby-2.3.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker'
14:01:10 rails.1   | Started GET "/cable" for 127.0.0.1 at 2017-05-04 14:01:10 +0200
14:01:10 rails.1   | Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2017-05-04 14:01:10 +0200
14:01:10 rails.1   | Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
14:01:10 rails.1   |   User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = 2 LIMIT $1  [["LIMIT", 1]]
14:01:10 rails.1   | [ActionCable] [[email protected]] Registered connection (Z2lkOi8vYXV0b2Nvb3JkMy9Vc2VyLzI)
14:01:10 rails.1   | +++++++++++++ subscribed method

The last line is just the puts from the subscribed method in the channels. It is there so I can follow how the data flow

Error I get in the chrome console is:

Uncaught TypeError: Cannot read property 'received' of undefined
    at t.notify (eval at <anonymous> (application.js:1187), <anonymous>:1:1715)
    at t.message (eval at <anonymous> (application.js:1169), <anonymous>:1:1778)

The app/channels/users_channel.rb looks like this:

class UsersChannel < ApplicationCable::Channel  
  def subscribed
    puts "+++++++++++++ subscribed method"
    stream_from 'users_channel'
  end

  def speak(data)
    puts "+++++++++++++++ speak method: #{data}"
    ActionCable.server.broadcast 'users_channel', message: data['message']
  end
end 

And the part of the react component (component name is ) that gets and sends data to backend looks like this:

...
  componentDidMount() {
    console.log("component did mount") //I see this in the console

    this.props.cable.subscriptions.create('UsersChannel', {
      message: "messsage",
      connected: function () {
        setTimeout(() => this.perform('speak',
          {data: "some dataaaa"}),
          1000);
      },

      received: function(data) {
        console.log(data);
      }
    });
  }
...

In my react root file I have:

...
import ActionCable from 'action-cable-react'

var actionCable = ActionCable.ActionCable
var cable = actionCable.createConsumer('ws://localhost:5000/cable');
console.log(cable)
/*
console.log(cable) outpust:

n {url: "ws://localhost:5000/cable", subscriptions: t, connection: t, connectionMonitor: t}
> connection: t
> connectionMonitor: t
> subscriptions: t
> url: "ws://localhost:5000/cable"
*/

  ...

  ReactDOM.render(
    <Application cable={cable} />,
    document.getElementById('application')
  );

This is my first try with websockets and I have no clue what's going on. I googled some blogposts and questions on stackoverflow about this topic but I can't get it work. I would be really grateful if you could help me to puts some data from the rails cabel and console.log some data in the browser.

Thank you!

2
  • 1
    This is not really an answer, but just a suggestion: checkout ruby-hyperloop.io Everything you are trying to do works out of the box, plus you write everything in ruby (client and server.) Also there is an active gitter community at gitter.im/ruby-hyperloop/chat if you need help Commented May 4, 2017 at 14:59
  • 1
    I recommend that you look into the Ruby-on-Rails ActionCable client. Much like socket.io, ActionCable implements a communication protocol over the Websocket connection and isn't the same as raw web sockets. You can use raw web sockets with RoR using middleware (such as plezi) or other solutions. Commented May 6, 2017 at 5:58

1 Answer 1

1

See my comment above. It's hard to answer your question due to the amount of debug necessary. However, if you can't use http://ruby-hyperloop.io then my suggestion would be to use pusher-faker as your websocket transport. (see the pusher-faker gem) its easy to setup, and I have found it much easier to diagnose system problems. Once you get things working you can switch back to action-cable.

I know it's not a great answer, but it's what I would do :-)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.