# How to use Rails ActionCable from an external client application

Photo by [Umberto](https://unsplash.com/@umby?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

> WebSockets is a beautiful way to allow the client-server communication using a persistent bidirectional channel without the client having to poll the server.

In this article **I’d like to explain how to get started with websocket in Ruby on Rails from a generic application**. I wont’ dive into what is a Websocket or how to create a Rails project. I’ll just leave some links at the end of this article.

## First of all, WebSocket in Rails are called `ActionCable`.

### The problem

Tutorials from the [official documentation](https://guides.rubyonrails.org/action_cable_overview.html#parent-channel-setup) or others like [this one](https://dev.to/nkemjiks/simple-chatroom-with-rails-6-and-actioncable-3bc3) explain how to configure the server part and show the code to subscribe and communicate from a Javascript frontend using the `rails/actioncable` node module. But **what if you have an API-only Rails project or you have a frontend other than JS**, like an Android or an iOS app? This is why I wrote this article.

### Get started!

Let’s suppose we’ve a _Rails_ project and you run the command below
```sh
rails generate channel Chat
```

it will generate a file called `<your_name>_channel.rb` where we can handle the client subscriptions or/and we can write custom methods that will be called by the clients… To keep the things simple we’ll implement the `subscribed` method and we write from scratch a custom dummy method (`my_method`) that receive a `data` parameter. We’ll see later what `data` is. Let’s replace `<your_name>` with `ChatChannel` for this example. Here’s how file looks like.

```ruby
class ChatChannel < ApplicationCable::Channel
  def subscribed
    logger.info "subscribed"
    stream_from "chat_channel"
  end

  def my_method(data)
    puts data
  end
end
```

> Our goal is reach the `subscribed` and the `my_method` methods from an external client other than JS or out of our Rails project. _Let’s start!!!_

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1637873018968/FXJfTkWB_.jpeg)

Photo by [Braden Collum](https://unsplash.com/@bradencollum?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

_First question_: how to create a WebSocket client? Or can we use a “Postman” like client already available?

There are many ways and libraries to establish a WebSocket connection for many platforms, but to get started I suggest this ready to use WebSocket clients

*   [http://www.websocket.org/echo.html](http://www.websocket.org/echo.html)
*   [this Chrome plugin](https://chrome.google.com/webstore/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn)

_Second question_: which URL should I call? In my project routes I can’t see anything related to `ActionCable`

*   Firstly we have to change the protocol from `http/https` to `ws`.
*   Let’s suppose that our Rails project runs on `localhost`, port 3000.
*   By default without specifying anything else, Rails expose the WebSocket service on `/cable` path

Putting these things together **the URL is `ws://localhost:3000/cable`**

_Third question_: how we communicate?

**Basically with JSON** **messages as specified by WebSocket protocol**. Like the `rails/actioncable` JS module, libraries provides an “SDK way” to manage these messages, but in our simple web clients we have a “Message field” to write the command in, nothing more. I strived to find what to format the request and at the time I write I guess there is a lot more to find out. To guide me to the right direction i found these two articles ([1](https://medium.com/@emikaijuin/connecting-to-action-cable-without-rails-d39a8aaa52d5), [2](https://thoughtbot.com/blog/talking-to-actioncable-without-rails)).The *2* also explain how to authenticate the user. To see the things working for a “step 0” in a simple way I’ll ignore this step. From the *1* I tried to copy/paste the string in the `sendTXT` method in the web client Message field as is (even with begin/end double quotes and all escape characters: `“{\\”command\\”:\\”subscribe\\”,\\”identifier\\”:\\”{\\\\\\”channel\\\\\\”:\\\\\\”ArduinoChannel\\\\\\”}\\”}”` ) but it didn’t work (I changed the name to my channel name first). I tried to remove the begin/end quotes and I thought that a problem was that the escape characters were too many. Hence I tried to serialize a dictionary representing the JSON above with the help of the Rails console . I finally obtained this JSON:
```json
{"command": "subscribe","identifier": "{\"channel\": \"ChatChannel\"}"}
```

<iframe src="https://giphy.com/embed/a0h7sAqON67nO/twitter/iframe" width="435" height="244" frameborder="0" scrolling="no"></iframe>

**It works!!!!** The web console answerd me “welcome”! Just take a look at the Rails log to be sure that the `subscribed` method had been called and printed “subscribed”. Yes!!! All right, then: How to call `my_method` method now?

_Here’s the best part_: **we can pass as many parameters we want** and we can call any methods with a very similar JSON

```json
{"command": "message","identifier": "{\"channel\": \"ChatChannel\"}", "data":"{\"action\": \"my_method\", \"code\":\"a\"}"}
```

The differences:

*   the command type has changed from “subscribe” to “message”
*   identifier **must** remain the same as the subscription
*   we added the `data` key with a JSON string (with all the escape characters)

Let’s send this message from the console and have a look at the Rails log. We’ll see these lines

*   `ChatChannel#my_method({“code”=>”a”}).` It recognized the `action` keyword and interpreted the JSON as an hash parameter. If we print the `data` parameter we obtain indeed `{“action”=>”my\_method”, “code”=>”a”}`

### Our goal has reached!!! Great!

Just a little last thing: in a normal Rails (http) controller method you can write this code:
```ruby
ActionCable.server.broadcast("chat_channel","An update has arrived...")
```

You’re dispatching via WebSocket on the `chat_channel` the “An update has arrived…” string: this will be printed even on your web console. **Doesn’t it look like a notification**

<iframe src="https://giphy.com/embed/3o6vY59s91hWsxASYM/twitter/iframe" width="435" height="315" frameborder="0" scrolling="no"></iframe>

### Further references

To learn about WebSocket or creating a Rails project

*   [What is WebSocket?](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
*   [Create a Rails app with Docker](https://docs.docker.com/compose/rails/)
*   [Rails official guide to create a new project](https://guides.rubyonrails.org/getting_started.html)

*Thanks for reading…*
