I'm playing around with the new ActionCable feature. Is there a way of communicating with the ActionCable server using say socket.io or from an application using React or ReactNative?
Perhaps I'm confusing the correct use of ActionCable and it is not intended to be used as a let's say API replacement and it is meant to be used as a supporting front end technology for the same app.
Any good example or guide to use ActionCable as standalone WS server would be appreciated if this is possible.
You can interact with ActionCable as you would normally with any WebSocket libraries.
To do so, you would stream from a Channel in Rails:
class ExampleChannel < ApplicationCable::Channel
def subscribe
stream_from 'example'
end
end
Then, you may connect to the Rails WebSocket through your stand-alone client and subscribe to the message using the ActionCable protocol:
function Socket(url) {
const ws = new WebSocket(url);
ws.onopen(() => {
ws.send('{"command":"subscribe","identifier":"{\"channel\":\"ExampleChannel\"}"');
});
}
Reference:
http://edgeguides.rubyonrails.org/action_cable_overview.html#channels
https://github.com/NullVoxPopuli/action_cable_client/blob/master/README.md
Related
I'd like my Rails app to be able to listen and publish to ActiveMQ queues.
This article gives examples of how to use a ruby STOMP client, and a gem activemessaging that integrates that client into a Rails app. The functionality there seems ideal, but the activemessaging gem seems to no longer be maintained.
There are lots of resources on using rabbitMQ instead of ActiveMQ, but I'm trying to improve my Rails app's integration with an existing Java stack that's already using ActiveMQ.
So does anyone know of a gem I can use to achieve similar functionality to that of the activemessaging gem? I can't find one, so failing that:
How would I initialise a Stomp client with a persistent connection to my activeMQ instance inside the context of my Rails app, such that 1) The lifecycle of the client is tied to that of the ruby process running my app, not the request-response procedure, and 2) I get to consume to messages using code such as Active Record models or service objects defined in my app?
Thanks in advance.
According to the ActiveMessaging project website:
ActiveMessaging is a generic framework to ease using messaging, but is not tied to any particular messaging system - in fact, it now has support for Stomp, AMQP, beanstalk, Amazon Simple Queue Service (SQS), JMS (using StompConnect or direct on JRuby), WebSphere MQ...
So, it's an interface to simplify integration between various messaging protocols and/or providers. However, since your using a standardized messaging protocol (i.e. STOMP) you don't really need it.
I recommend you simply use this STOMP gem which is referenced in the original article.
STOMP, as the name suggests, is a very simple protocol. You should be able to use it however you need in your application.
As there's so little out there on this topic I thought I'd share the solution I came up with. Having established that using the STOMP gem directly is the way forward let me re-iterate the key challenges:
How would I initialise a Stomp client with a persistent connection to
my activeMQ instance inside the context of my Rails app, such that
1) The lifecycle of the client is tied to that of the ruby process
running my app, not the request-response procedure, and
2) I get to consume to messages using code such as Active Record models or service
objects defined in my app?
Part 1) turned out to be a bad idea. I managed to achieve this using a Rails initializer, which worked fine on my local. However, when I ran it in a staging environment I found that my message listeners died mysteriously. What seems to happen is that production web servers spawn the app (running the initializers), fork the process (without running them) and kill processes at random, eventually killing the listeners without ever having replaced them.
Instead, I used the daemons gem to create a background process that's easy to start and stop. My code in lib/daemons/message_listener.rb looked something like this:
require 'daemons'
# Usage (from daemons dir):
# ruby message_listener start
# ruby message_listener status
# ruby message_listener stop
# See https://github.com/thuehlinger/daemons for full docs.
# Require this to get your app code
require_relative '../../config/environment'
Daemons.run_proc('listener.rb') do
client = nil
at_exit do
begin
client.close
rescue # probably means there's no connection to close, do nothing to handle it.
end
end
client = Stomp::Client.new(your_config_options)
# Your message handling code using your rails app goes here
loop do
# I'd expected that subscribing to a stomp queue would be blocking,
# but it doesn't seem to be.
sleep(0.001)
end
end
I need to use Websocket in my Rails API (only) app. There's no any server-side rendering for pages. The app is a JSON-only backend for Angular and Xamarin. I saw that a lot of tutorials use coffescript as ActionCable client inside Rails, but it's not my case.
The question is: how to use ActionCable as API-only, outside of Rails' coffescript, like for Android, iOS, Angular and React client?
I found different and useful resources but I'm still a bit confused.
1: ActionCable usage for Rails API - it seems the best, but how can I find all JSON commands exchanged by the ActionCable framework?
2: Similar Question to the mine
3: Rails API Websocket GEM - ok, is not ActionCable, but this guy had compiled coffescript into JS and ported it into project. Not useful for Mobile development.
If there are different solutions or better knowledges, please tell me. I need to "hack" this to turn it working.
EDIT : I found also this repo action-cable-js but how to integrate it?
Actioncable for API only has got official support and there's this npm package called actioncable which has decoupled support for communication with actioncable server using an API only approach.
npm install actioncable
then in your react/angular code
import ActionCable from 'actioncable';
# create a connection with the actioncable server
# use ws:// for http and wss:// for https
const cable = ActionCable.createConsumer("ws://your-backend-server.com/cable");
# now you create a subscription
my_subscription = cable.subscriptions.create("MessengerChannel", {
connected: function() {
console.log("You've subscribed to the Messenger Channel");
},
disconnected: function() {
console.log("You've disconnected from the Messenger Channel");
},
received: function (received_data) {
# broadcast data from the Messenger channel is received here
console.log(received_data);
}
})
At the back-end side, you need to mount actioncable, for that do this
# routes.rb file
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
end
I hope my answer could be useful for anybody. I finally discovered a library called actioncable-js that helped me in the Angular project.
But is not enough. For the Mobile projects I need to use "low level" commands to interact with Action Cable server.
The protocol is here: protocol.
But if you need more about you should look deep inside the gem.
I'm working in a Rails 4.2.7 application and need to use WebSockets. Unfortunately I can't upgrade to Rails 5 and use Action Cable for this.
The application is using Puma in production, I say this because I found some gems that are meant to be used for Web Sockets but they work just in Thin app server but not with Puma app server.
Is there any easy solution for this?
Specifically what I need to do is trigger an event to my clients (browsers in this case) every time my model is updated
class MyModel < ActiveRecord::Base
after_commit :notify_users, if: :some_condition
def notify_users
# Trigger a web socket event to my clients here
end
end
I have tried with https://github.com/websocket-rails/websocket-rails, and the message gets sent according to the logs, but I'm not receiving it on the browser, and unfortunately it seems that the gems is not maintained anymore.
Is there a solutions that might work for this situation? Thanks
Based on this issue it sounds like the best bet is tubesock
There's not TOO much documentation on action cable so I'm a little lost on this.
I'm playing with a rails 5 app, and I'm trying to use the rails5 app as purely an api and hosting my JS elsewhere. So when I start my actioncable server, i am able to connect to the websocket pretty easily just using my built in browser socket support with:
var socket = new WebSocket('localhost:3000/cable')
// and then do
socket.onmessage = function(data) { console.log(data) }
I connect successfully. I'm getting pings in the form of
MessageEvent {isTrusted: true, data: "{"type":"ping","message":1462992407}", ... etc
Except I can't seem to broadcast any messages down to the client. I tried:
ActionCable.server.broadcast('test',{ yes: true })
But only the pings come in. ActionCable comes with its own concepts that I haven't wrapped my head around fully yet like channels and stuff which "just work" in rails apps. But how can I successfully build a separate standalone JS app using actioncable's socket server?
I use ActionCable with an iOS application. Everything works just fine.
ActionCable uses pub/sub pattern.
Pub/Sub, or Publish-Subscribe, refers to a message queue paradigm
whereby senders of information (publishers), send data to an abstract
class of recipients (subscribers), without specifying individual
recipients. Action Cable uses this approach to communicate between the
server and many clients.
Which means that you should create a new channel first,
rails g channel my_channel
Then in your channel send some test message:
# app/channels/my_channel.rb
class MyChannel < ApplicationCable::Channel
def subscribed
stream_from "my_channel"
ActionCable.server.broadcast "my_channel", 'Test message'
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
Then send the following to your server:
{'command': 'subscribe', 'identifier': {\'channel\':\'MyChannel\'}}
In return you'll get your first frame.
I'm wondering the way to push content in my site in real time..
I've researched some time and I realized that there are many ways to do this work.
Some considerations first:
I have a Rails 3 App with some social functionality..one of the features I want to achieve is to notify my users when a new activity is created.
My first approach was to implement SSE and a controller that searches in the DB for new registries after the last loaded activity.
This can work but this requires too many DB queries when all I need is to push the activity to all active users (related with that activity) when a new activity is created, without the need to do DB queries..
My second approach was to create a route pointing to a controller and an observer to catch when an new activity is created, later pass the current activity created to the controller and finally render the activity partial through SSE.
Here comes my problem.. how can connect the observer with the controller and pass it the current activity to be rendered?
And there, can I use another controller type such as a Metal Controller or even an Abstract one?
In this point I realized that could be another approach to do this job..
It'd be really nice if I could find a way to do this without having to develop it in another language or framework.. I think that should have a gem that could do real time apps easier..
What do you think?? I'm on the right way or what I should do to achieve this??
Many Thanks!!
Rails 3.0+ Push Content in Real-time with PubNub
In order to safely and securely push real-time updates to your users with some social functionality on your web site or web app there are, as you say, many options available and many nuances to consider with this as well. There is a gem for this! And I will help you get started by providing a simple start guide here for your Rails 3.0+ app and web site. First you'll want to run gem install pubnub which is the real-time component known as PubNub that will allow you to send notifications directly to targeted users or a group of users on your website and apps. This allows you to target only those who are online and interested in receiving the notifications from your Rails server. You can consider this as efficient server-sent events that require no DB Lookup or other resource intensive operations on your servers.
Ruby GEM Install
gem install pubnub
Require PubNub GEM
require 'pubnub'
Initialize The PubNub Class
pubnub = Pubnub.new(
:publish_key => 'demo', # publish_key only required if publishing.
:subscribe_key => 'demo', # required always
:secret_key => nil, # optional - message signing
:cipher_key => nil, # optional - AES 256 Crypto
:ssl => true # optional - SSL 2048bit
)
From Rails 3.0+ Send Messages to the Web App
Now from your Rails App with the pubnub class ready, you can send any kind of JSON data type including a String, Number, Array and Dictionary/Object:
a "String"
a Number 123
an array [ 1, 2, 3 ]
an object { :a => "apple" }
The following code will show you the process which will pass a message from your Rails App directly to the browser or web app that you users are running. Essentially sending the data to your users when you need to directly from your server. The pubnub.publish(...) function will serialize the message you send as a JSON for transport to your mobile and web apps.
## Broadcast or Unicast to Browser App User(s)
pubnub.publish(
:channel => "event_feed_channel",
:message => { :event => "update", :from => "Jay", :feed => "New Updates!" },
:callback => lambda { |info| puts info }
)
This process works great for performance and security considerations and never requires DB queries; saving you from hammering on your Database server and other resource intensive operations. You may consider this process as SSE (Server-Sent Events) while you are using the PubNub GEM in your Rails applications.
Using the PubNub GEM you are essentially sending events from your Server direct to your User's Browser/App. It removes the need for client-side periodic AJAX requests. This is because you are only sending data to your user's when new information is available. You may also consider using more PubNub Real-time Network features like Presence and Storage/Playback by visiting the home site to learn more details about the Ruby features. And also use the Developers Dev Console for debugging if needed during your integration into your Rails code.
Setup Browser to Receive Server-Sent Events
Next you need to setup your app to receive the Server-Sent Events by running init and passing in the
<script src=http://cdn.pubnub.com/pubnub-3.4.2.min.js ></script>
<script>(function(){
// Class Setup
var pubnub = PUBNUB.init({ subscribe_key : 'demo' });
// Event Hook Setup
pubnub.subscribe({
channel : "event_feed_channel",
message : function(m){ pubnub.events.fire( m.event, m ) }
});
// RECEIVE the "update" Server Broadcast Event in the Browser
pubnub.events.bind( "update", function(message) {
console.log( "update a <div> with received event: ", m );
} );
})();</script>
Note you may be interested in Advanced Subscribe Connectivity Options and Events.
Notice how the "update" event is identical to the :event => "update" message value in the ruby code. This means that the event will be triggered based on the name you supply and you need to bind the event to trigger code to execute on your Web App page. Inside this triggered event you will update the User Interface with any relevant details that the user would want to see on their screen in real-time.
Also notice the :channel => "event_feed_channel" is the publish channel, and this must be identical as the subscribe channel in the JavaScript client code.
If you want to read the source code of the Ruby GEM, it is available via GitHub PubNub Ruby-based APIs.
These are the basics for getting started with Ruby 3.0+ Apps and sending events directly from your server to your End-users. Note this also works for Mobile Apps that run on iOS Web Browsers or Android Browsers. Also old versions of IE are supported for this mechanism. In addition you could optionally consider server sent events from your Rails servers directly to Native iOS applications and Native Android Applications. If you have any questions ask them here on this Forum.
I've built a realtime rails gem and a sample realtime server (node.js) which enables easy realtime messaging without the need of a paid, third party, such as Pusher or PubNub. It works with Rails 3+.