DEV Community

Alexandre
Alexandre

Posted on

O básico de Action Cable em Rails 7

Se você quer criar um chat em tempo real, ou então criar um joguinho multiplayer, então para fazer em Rails, será necessário usar o Action Cable.

Então, vamos lá.

O que é Action Cable?

Action Cable integra perfeitamente com WebSockets com o resto da sua aplicação Rails. Isso permite que recursos em tempo real sejam escritos em Ruby no mesmo estilo da sua aplicação, enquanto ainda é performático e escalável. Isso é uma oferecimento full-stack que providencia o framework Javascript do client-side e framework Ruby do server-side.

Agora, que nós sabe o que é Action Cable, vamos entender algumas termologias.

Termologias

Connections ou Conexões

Connections (Conexões) formam a base do relacionamento cliente-servidor. Um único servidor Action Cable pode lidar com várias instâncias de conexão. Um único usuário pode ter vários WebSockets abertos para seu aplicativo se usar várias abas do navegador ou dispositivos diferentes.

Consumers ou consumidores

O cliente de uma conexão WebSocket é chamado de consumer (consumidor). Em Action Cable, o consumer é criado pelo framework javascript do client-side

Channels ou Canais

Cada consumer pode, por sua vez, assinar vários channels.
Cada canal encapsula uma unidade lógica de trabalho, similar o que controller faz no típico MVC. Por exemplo, você pode ter um ChatChannel e um PresencaChannel e um consumer pode assinar um ou ambos canais. No minimo, o consumer deve assinar pelo menos um canal.

Subscribers ou Assinantes

Quando o consumer está assinado em um channel, ele pode agir como um subscriber (assinante). A conexão entre o subscriber e o channel é, surprise-surprise, chamado de assinatura. Um consumer pode agir como um subscriber de um determinado channel quantas vezes quiser. Por exemplo, um consumer pode assinar várias sala de conversa ao mesmo tempo.

Pub/Sub

Pub/Sub ou Publish-Subscribe (Publicar-Assinar) refere-se a uma paradigma de fila de messagens por meio do qual os remetentes de informações (publishers), enviam dados apara uma classe abstrata de destinatários (subscribers), sem especificar os destinatários individuais. Action Cable usa essa abordagem para comunicar entre o servidor e vários clientes.

Broadcastings ou Transmissões

Um broadcasting é um link pub/sub em que qualquer coisa transmitida pelo broadcaster é enviada diretamente para os subscribers do channel que estão transmitindo essa chamada broadcasting. Cada canal pode transmitir zero ou mais broadcastings.

Tendo o conhecimento das termologias, vamos criar uma aplicação.

Criando uma aplicação

O aplicativo que vou criar é um chat.

rails new chat
cd chat
rails g controller Chat index
Enter fullscreen mode Exit fullscreen mode

Coloque a rota chat#index como root.

# config/routes.rb
Rails.application.routes.draw do
  root 'chat#index'
end
Enter fullscreen mode Exit fullscreen mode

Abra o arquivo app/views/chat/index.html.erb e coloque o código abaixo.

<!-- app/views/chat/index.html.erb -->
<div>
  <textarea id="input"></textarea>
  <button id="button">enviar</button>
</div>
<div id="chat"></div>
Enter fullscreen mode Exit fullscreen mode

Agora, vamos colocar o Action Cable.

Instalando o Action Cable

Como a nossa aplicação é um chat, então vamos criar um channel Chat.

Para criar, basta usar o generator.

rails g channel Chat
Enter fullscreen mode Exit fullscreen mode

Tem um arquivo que fica no app/channels/application_cable/connection.rb que fica responsável pela conexão.

Porém, você tem fazer a parte de autenticação e autorização, mas como a minha aplicação não tem autenticação, então eu vou ignorar essa parte.

Mas eu vou deixar um exemplo do código de como seria se tivesse uma autenticação.

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

    def connect
      self.current_user = find_verified_user
    end

    private
      def find_verified_user
        # se você estiver usando cookie para autenticação
        verified_user = User.find_by(id: cookies.encrypted[:user_id])
        # se você estiver usando session para autenticação
        verified_user = User.find_by(id: cookies.encrypted['_session']['user_id'])
        # se por acaso, você estiver usando uma gem para autenticação, terá pesquisar sobre isso.
        if verified_user
          verified_user
        else
          reject_unauthorized_connection
        end
      end
  end
end
Enter fullscreen mode Exit fullscreen mode

Você pode observar o identified_by, ele cria um identificador de conexão, ou seja, você pode usar current_user para saber quem é o usuário que está conectado em uma conexão.

Agora, vamos focar no client-side.

Client Side

Abra o arquivo app/javascript/channels/chat_channel.js e coloque o código abaixo.

// app/javascript/channels/chat_channel.js
import consumer from "channels/consumer"

// o consumer vai ser criado aqui e vai tentar assinar no canal ChatChannel
consumer.subscriptions.create("ChatChannel", {
  connected() { // vai executar essa método se a conexão foi sucedida
    this.input = document.getElementById("input")
    this.chat = document.getElementById("chat")

    const button = document.getElementById("button")

    button.addEventListener("click", this.enviar_mensagem.bind(this))
  },

  received(dados) { // Aqui recebe os dados do server side
    this.chat.innerHTML += `<p>${dados.mensagem}</p>`
  },

  enviar_mensagem() { // Aqui vai enviar os dados para server side
    let dados = {mensagem: input.value}

    this.perform("mensagem", dados)
    // isso vai enviar os dados para action mensagem do server side

    input.value = ""
  }
});
Enter fullscreen mode Exit fullscreen mode

Server side

Abra o arquivo app/channels/chat_channel.rb e coloque o código abaixo.

# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  # vai executar esse método se o usuário vai fazer uma conexão
  def subscribed
    # o stream_from vai assina em um broadcasting com nome 'chat', isso é útil para criar grupo. 
    stream_from "chat"
  end

  # aqui é a action que recebe os dados do client side
  def mensagem dados
    # isso vai envia a dados para os subscribers (assinantes). O primeiro argumento é o nome do broadcasting, como você pode ver que é igual ao argumento do `stream_from`.
    ActionCable.server.broadcast("chat", dados)
  end
end
Enter fullscreen mode Exit fullscreen mode

Agora, execute o rails server e abre duas abas do navegador com a url localhost:3000, tente manda uma mensagem e verá que a outra aba vai receber a mensagem.

Com isso, nós terminamos por aqui, porém eu vou fazer, um dia, um post, em que vou aprofundar mais o action cable criando um joguinho simples.

Então é isso, tchau!

Top comments (3)

Collapse
 
hadannpires profile image
hadannpires

Obrigado pela explicação! Gostaria de pedir a continuação, pfv!

Collapse
 
xandekk profile image
Alexandre

Bem, posso até tentar, mas como eu estou um pouco ocupado agora e, além disso, não mexo com Rails desde o ano passado e também não sei se houve alguma atualização sobre isso, mas tentarei.

Collapse
 
xandekk profile image
Alexandre

Infelizmente, não vou fazer isso, porque ainda não abordei o Redis, banco de dados e a utilização de JavaScript no Rails. Afinal, não gosto de abordar assuntos que não foram apresentados e não tenho tempo para isso. Então é isso.