Daniel Olivares
Daniel Olivares

Reputation: 554

Rails 5 app (Action Cable) as Socket.io server AND client

I am now familiar with Action Cable (Rails 5 functionality) as an emitter or server of websockets. However, I am supposed to consume an API which sends the data over websockets (e.g. 'socket.provider.com?token=12345').

I made some tests with a plain Ruby file using socket.io-client-simple (https://github.com/shokai/ruby-socket.io-client-simple) and it works, but I am not sure on how this would work on a deployed Rails app. I'm guessing I need a separate process which listens constantly for events emitted by the API provider. Has anyone done something similar? I am going to use Heroku for deployment.

Note: I think using a client-side approach for receiving the websockets and then posting them to my Rails app (i.e. Javascript Socket.IO library) is not an option, since I need to receive AND persist some of the data coming from the events in real time and not depend of the connectivity of at least one client.

I'm also wondering if there is any way to automatically set Action Cable to act as a 'listener of events' somehow. Haven't read anything on that topic so far, but would love to see some suggestions on that direction.

Update: Here is the Ruby code I'm using so far to connect to the provider's websockets API:

require 'rubygems'
require 'socket.io-client-simple'

socket = SocketIO::Client::Simple.connect 'https://api.provider.com', token: '12345'

socket.on :connect do
  puts "connect!!!"
end

socket.on :disconnect do
  puts "disconnected!!"
end

socket.on :providerevent do |data|
  puts data
end

socket.on :error do |err|
  p err
end

puts "please input and press Enter key"
loop do
  sleep 100
end

Upvotes: 3

Views: 3992

Answers (1)

Graham Slick
Graham Slick

Reputation: 6870

ActionCable can't be listening to an external site's event on its own, so you'll have to combine socket.io and ActionCable.

ActionCable can send updates to the channel like this:

ActionCable.server.broadcast "channel_name", param1: your_param1, param2: your_param2

to update the channel when an event occured. The received action of your channel's coffeescript file is where you have to do something with it. From what I understand, you're looking for something like this in the controller where you would be listening for events:

def listen
  socket.on :connect do
    # persist your data 
    # example: @post = Post.create(...)
    ActionCable.server.broadcast "channel_name", post_title: @post.title
  end
end

and in your channel_name.coffee:

received: (data) ->
  console.log(data["post_title"])
  # do something

With this setup, you would be receiving events from the api, and broadcasting it to your channel. The page were the channel is setup would be updated each time your socket receives an event.

You should first follow DDH's tutorial, and then you'll probably understand better my solution (which is pretty easy to implement).

Upvotes: 3

Related Questions