2

I want to create a connection between rails ActionCable which will act as Server and NodeJs as Client.

This is my code in connection.rb file.

 # app/channels/application_cable/connection.rb
 module ApplicationCable
   class Connection < ActionCable::Connection::Base
    identified_by :uuid

    def connect
     self.uuid = SecureRandom.uuid
    end
  end
 end

This is code of my channel.

 # app/channels/socket_connection_channel.rb
 class SocketConnectionChannel < ApplicationCable::Channel
  def subscribed
   stream_from "socket_connect"
  end

  def speak
    ActionCable.server.broadcast("socket_connect",
                             message: "Connected")
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
   end

 end

And this is NodeJs code in server.js file

   const WebSocket = require('ws');

   const ws = new WebSocket('ws://0.0.0.0:3001/cable');

   ws.on('open', function open() {
     ws.send(JSON.stringify({'data': 'Sample Data'}));
   });

    ws.on('message', function incoming(data) {
     console.log(data);
     });

   ws.on('socket_connected', function incoming(data) {
      console.log('socket');
    });

When I run the server node server

  {"type":"welcome"}
  {"type":"ping","message":1497487145}
  {"type":"ping","message":1497487148}
  {"type":"ping","message":1497487151}

and on rails server displays the following logs

     Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2017-06-15 
    02:39:02 +0200
      Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
      Registered connection (5db66385-0923-4633-8837-ba957fc0a7f5)
      Received unrecognized command in {"data"=>"Sample Data"}

What I want to achieve is that node server will make the Websocket connection on rails ActionCable and subscribe to SocketConnect Channel and will transmit the data to Rails server via this channel.

I have found some examples of chat application on rails action server where the client and server both are on smae rails platform. But, I haven't found any example where client is on separate palatform than server.

But, I am unable to find any method to Subscribe for this channel and make a stable connection on both ends to transmit data and I also don't know how to get data from this request.

Please help me in this. Thanks in advance

Rails Developer
  • 402
  • 6
  • 18

1 Answers1

2

Try this. Sending subscribe and setting identifier for socketchannel is important point.

rails

# app/channels/socket_connection_channel.rb
 class SocketConnectionChannel < ApplicationCable::Channel
  def subscribed
   @uuid = params[:uuid]
   stop_all_streams
   stream_from "socket_connect_#{@uuid}"
   logger.info ">>> Subscribed #{@uuid}!"
  end

  def speak
    logger.info "[ActionCable] received message : #{data['message']}" 
    ActionCable.server.broadcast "socket_connect_#{@uuid}", message: "#{data['message']} from server"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
   end

 end

node.js

var App = {};

App.sendmessage = function(send) {
  data = {
    message : send,
    action : "speak"
  };
  message = {
    command: "message",
    identifier: JSON.stringify(App.param),
    data: JSON.stringify(data)
  };    
  App.ws.send(JSON.stringify(message));
}

App.connect_server = function() {         
  const WebSocket = require('ws');
  App.ws = new WebSocket('ws://0.0.0.0:3001/cable', ["actioncable-v1-json", "actioncable-unsupported"]);

  App.param = {channel: "SocketConnectionChannel", uuid: guid()};

  App.ws.on('open', function open() {
    data = {
      command: "subscribe",
      identifier: JSON.stringify(App.param)
    }
    App.ws.send(JSON.stringify(data));
  });  
  App.ws.on('message', function (event) {
    console.log(event);
  });
  function guid() {
   function s4() {
     return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
   }
   return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
  }
}
App.connect_server();

node.js

App.sendmessage("Hello world");

https://github.com/mwalsher/actioncable-js is also helpful for you.

Inkyu Han
  • 91
  • 5
  • Thanks for your response. When I write this code in separate `node.js` file and run server with `node node.js` command it shows me following error. `(function (exports, require, module, __filename, __dirname) { window.App = {}` `ReferenceError: window is not defined` – Rails Developer Jun 15 '17 at 03:53
  • window is not necessary. Just do it => "var App = {};" – Inkyu Han Jun 15 '17 at 04:56
  • after declaring `var App = {};` I am still getting error `window is not defined`. I assume it is associated with `HTML`/`DOM` object. But I am using only js file to run `server`. I don't know how can I initialize `window`. – Rails Developer Jun 15 '17 at 05:51
  • Thanks. You are awesome. It worked :) . Can you please share any reference or source where all the details/usage of other methods/functions is given. – Rails Developer Jun 15 '17 at 07:52
  • 1
    Refer this https://stackoverflow.com/questions/35320791/how-to-use-actioncable-as-api. It will be more helpful. :D – Inkyu Han Jun 15 '17 at 08:05