
Compartilhar:
Phil is Head of Developer Relations at Hookdeck, an asynchronous messaging platform, and a proud Vonage alumni.
Criação de um aplicativo de chat para atendimento ao cliente com o Action Cable do Rails 5 e SMS
O Rails 5 foi lançado com alguns novos recursos incríveis, como Turbolinks 5 e o modo API, mas o recurso que chamou nossa atenção foi a nova integração nativa com WebSocket no Action Cable. Essa nova abstração em torno do WebSocket está incorporada diretamente ao Rails e é perfeita para eventos em tempo real e comunicação bidirecional. Hoje vamos dar uma olhada em como construir uma experiência de atendimento ao cliente com base nela e na SMS API da Nexmo.
Um chat de atendimento ao cliente em Ruby on Rails 5
Neste tutorial, vamos criar um sistema de chat bidirecional de atendimento ao cliente para uma empresa que deseja se comunicar diretamente com seus clientes, não apenas pelo site, mas também por SMS. O aplicativo web servirá de interface para o “agente de atendimento ao cliente” e será desenvolvido com o Action Cable, enquanto os clientes poderão usar seus celulares para enviar mensagens de texto diretamente ao agente de atendimento.

Para facilitar as coisas, criamos um ponto de partida para nosso aplicativo e o colocamos no GitHub. É um aplicativo básico em Rails 5 com um MessagesController para criar novas mensagens em um tópico. Fornecemos alguns dados fictícios por meio do arquivo seed e uma interface de usuário bonita com a ajuda do Semantic UI.
Certifique-se de ter o Ruby 2.2.2 ou uma versão superior instalada. Em seguida, você pode baixar o código inicial deste tutorial no GitHub, caso queira acompanhar a programação.
Em seguida, acesse localhost:3000 no seu navegador e você poderá comentar nos tópicos existentes, mas nada será enviado por SMS por enquanto.
Todo o código para este ponto de partida pode ser encontrado no ramo no GitHub. Todo o código que adicionaremos a seguir pode ser encontrado no after . Para sua conveniência, você pode ver todas as alterações entre nosso ponto inicial e final no GitHub também.
SMS da Nexmo e Action Cable para Rails 5
A SMS API da Nexmo oferece baixa latência e alta taxa de entrega de mensagens, o que é ideal para o chat de atendimento ao cliente em tempo real. Analisaremos dois elementos principais: o envio e o recebimento de mensagens de texto e a exibição delas em tempo real no aplicativo web usando o Action Cable.
Para isso, vamos fazer as seguintes alterações em nosso aplicativo:
Ouvir mensagens de texto recebidas
Exibir uma nova mensagem em nossa interface do usuário com o Action Cable
Adicionar o Nexmo ao nosso aplicativo
Enviar novas mensagens por SMS a partir do agente de serviço (por meio da Nexmo)
Exibindo mensagens SMS recebidas com o Action Cable
Nosso primeiro passo será adicionar mensagens SMS recebidas ao nosso aplicativo. Para isso, precisaremos obter um número de telefone da Nexmo capaz de enviar e receber mensagens SMS.

Você pode comprar um número no Painel da Nexmoou usar o nexmo-cli e adquirir um diretamente pela linha de comando. Você pode encontrar suas credenciais de API na página de configurações da sua conta Nexmo
Por exemplo, para comprar um número de telefone do Reino Unido que comece com 07:
> npm install -g nexmo-cli
> nexmo setup <your_api_key> <your_api_secret>
> nexmo number:buy GB 447* --confirm
Number purchased
> nexmo number:list
4475555555555Quando uma mensagem SMS for recebida nesse novo número, a Nexmo chamará a URL do webhook que especificarmos. Por enquanto, vamos criar um webhook fictício que apenas retorne uma resposta JSON simples.
# app/controllers/text_messages_controller.rb
class TextMessagesController < ApplicationController
include ApplicationHelper
skip_before_action :verify_authenticity_token, :only => [:create]
# If webhooks are set up as GET requests
def index
render json: { state: 200 }
end
# If webhooks are set up as POST requests
def create
render json: { state: 200 }
end
end
Vamos acrescentar isso também à nossa routes.rb.
# config/routes.rb
Rails.application.routes.draw do
resources :text_messages
...
endSe você carregar agora localhost:3000/text_messages , você deverá ver uma resposta em JSON.
Para tornar seu aplicativo acessível publicamente pelos webhooks do Nexmo, você tem algumas opções. Se tiver a sorte de ter um IP público em sua máquina, você já está pronto para começar; para o resto de nós, podemos implantar o aplicativo, usar um túnel SSH ou minha solução favorita: usar o incrível ngrok .
Após a instalação, você pode obter uma URL pública da seguinte forma:
Assim que seu aplicativo estiver disponível ao público, poderemos vincular nosso número a uma URL de webhook. A partir de então, sempre que for recebida uma mensagem SMS, será feita uma chamada para essa URL. Para isso, vamos usar novamente o nexmo-cli.
Se ocorrer algum erro nesta etapa, verifique se você está usando o número de telefone da Nexmo cadastrado na sua Account e se a URL do webhook está acessível ao público.
O próximo passo é ampliar nossa ação para receber a mensagem, analisar a resposta e salvá-la em nosso banco de dados.
# app/controllers/text_messages_controller.rb
# If webhooks are set up as GET requests
def index
create_message(params)
end
# If webhooks are set up as POST requests
def create
create_message(params)
end
def create_message(params)
message = Message.create!(
number: params[:msisdn],
text: params[:text],
inbound: true
)
render json: { state: 200 }
endExperimente! Inicie seu servidor (e o ngrok, se necessário) e envie uma mensagem para o seu número da Nexmo. Em poucos segundos, a mensagem deve ser processada pelo seu aplicativo. Atualize a página para ver sua nova mensagem.
Exibindo mensagens com o Action Cable
Obviamente, não queremos ter que atualizar a página toda vez que chega uma nova mensagem, e é exatamente aí que o Action Cable entra em cena.
A Action Cable utiliza canais para a comunicação entre editores e assinantes. No nosso caso, vamos enviar o number e o html da nossa nova mensagem no messages canal.
Vamos começar adicionando uma nova linha ao nosso TextMessagesController:
# app/controllers/text_messages_controller.rb
def create_message(params)
...
send_cable(message)
render json: { state: 200 }
endComo você pode ver, separamos nossa publicação em um método auxiliar, já que vamos querer reutilizá-la mais tarde.
Nosso helper é bem simples — ele gera o HTML e, em seguida, passa o HTML e o número para o ActionCable.server.broadcast método.
# app/helpers/application_helper.rb
def send_cable message
html = render_message(message)
ActionCable.server.broadcast 'messages',
number: message.number,
html: html
end
def render_message message
ApplicationController.render({
partial: 'messages/message',
locals: { message: message }
})
endPara receber a mensagem no front-end, precisaremos nos conectar ao nosso servidor por meio de um novo WebSocket e ficar à escuta no messages canal para detectar novas mensagens que cheguem.
Começamos montando ActionCable em nossas rotas.
# config/routes.rb
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
...
end
Isso disponibilizará um ponto de conexão WebSocket em http://localhost:3000/cable ao qual podemos nos conectar usando nosso JavaScript da seguinte maneira.
// app/assets/javascripts/channels/messages.js
App.cable.subscriptions.create('MessagesChannel', {
received: function(data) {
// process data
}
});Então, como o Rails sabe que os MessagesChannel corresponde ao messages fluxo? Ele não sabe. Precisamos especificar isso nós mesmos.
# app/channels/messages_channel.rb
class MessagesChannel < ApplicationCable::Channel
def subscribed
stream_from "messages"
end
end
Em exemplos mais complexos, você poderia criar dinamicamente o nome do canal com base no usuário autenticado, em parâmetros adicionais e muito mais. No nosso exemplo, estamos mantendo as coisas simples e apenas definindo de forma estática uma assinatura do messages stream.
Por fim, precisamos atualizar nosso código JavaScript para inserir o HTML que recebemos pelo cabo em nossa interface de usuário.
// app/assets/javascripts/channels/messages.js
App.cable.subscriptions.create('MessagesChannel', {
received: function(data) {
var list = $('.numbers');
var thread = $('.thread');
var number = thread.data('number');
var latest = $('.message[data-number="'+data.number+'"]');
// prepend to message thread
if (thread.length &&
data.number == number) thread.prepend(data.html);
// prepend to list of ongoing threads
if (list.length) {
latest.remove();
list.prepend(data.html);
}
$('.message:first').transition('flash');
}
});
Esse código faz algumas coisas. Primeiro, ele localiza o .thread e .numbers elementos dentro do DOM. Em seguida, se estivermos visualizando mensagens (na views/messages/show.html.erb visualização) correspondente ao número de origem da mensagem recebida, colocamos a mensagem no início. Se estivermos na index visualização (views/messages/index.html.erb), exibindo a mensagem mais recente de todos os Numbers, substituímos os detalhes da mensagem existente pelo novo código HTML.
Para que tudo isso funcione, precisamos adicionar um data-number atributo ao .thread elemento e a cada .message elemento, para que possamos saber a qual número eles estão relacionados.
<!-- app/views/messages/show.html.erb -->
<div class="ui one cards thread" data-number="<%= params[:id] %>">
<!-- app/views/messages/_message.html.erb -->
<%= link_to "/messages/#{message.number}",
class: 'ui card message',
data: { number: message.number } do %>
É isso aí sobre o Action Cable! Inicie seu servidor (e o ngrok, se necessário) e envie uma mensagem para o seu número Nexmo. Em poucos segundos, a mensagem deve ser processada pelo seu aplicativo e, desta vez, você não precisa atualizar a página para ver a nova mensagem. Em vez disso, ela aparecerá assim que o Action Cable a publicar no messages fluxo.
Responder a mensagens
Agora que já temos o recebimento de SMS funcionando, vamos atualizar nosso código atual para enviar novas mensagens do agente de atendimento diretamente para o número de telefone do cliente.

Para enviar uma mensagem SMS pelo Nexmo, precisaremos adicionar o nexmo gem ao projeto.
# Gemfile
gem 'nexmo'
group :development, :test do
gem 'dotenv-rails'
endComo você pode ver, também adicionamos o dotenv-rails gem. Isso serve apenas para facilitar as coisas, pois permitirá que o aplicativo carregue nossas credenciais de API a partir de um .env arquivo. A nexmo gem detecta automaticamente essas variáveis de ambiente e as utiliza para inicializar o cliente. Você pode encontrar suas credenciais na página de configurações da sua conta Nexmo.
# .env
NEXMO_API_KEY=<your_api_key>
NEXMO_API_SECRET=<your_api_secret>
NEXMO_NUMBER=<your_nexmo_number>Também adicionamos o nosso NEXMO_NUMBER ao .env arquivo aqui também.
A seguir, vamos transformar nosso novo formulário de mensagem em um remote formulário e usar ActionCable para mostrar ao cliente os novos envios, em vez de redirecionar a página.
<!-- app/views/messages/_form.html.erb -->
<%= form_for(@new_message, remote: true, html: { class: 'ui form error' }) do |f| %>
Em nosso controlador, vamos substituir o redirecionamento por algo mais familiar.
# app/controllers/messages_controller.rb
if message.save
send_cable(message)
send_sms(message)
endO send_cable é o nosso editor do Action Cable de antes, e o send_sms será implementado em seguida.
Antes de continuarmos, porém, vamos criar uma create.js.erb para que nossa ação não gere erros por falta de uma visualização. Usaremos essa visualização também para limpar nosso textarea quando o formulário for enviado.
# app/views/messages/create.js.erb
$('textarea').val('');Por fim, vamos enviar o SMS para o número correto com a mensagem do agente de atendimento ao cliente.
# app/helpers/application_helper.rb
def send_sms message
Nexmo::Client.new.send_message(
from: ENV['NEXMO_NUMBER'],
to: message.number,
text: message.text
)
endÉ isso aí, agora você já deve ter uma integração completa de mensagens SMS bidirecionais com o Rails, com a ajuda do Nexmo e do Action Cable do Rails 5. Reinicie o servidor, se necessário, e envie algumas mensagens para si mesmo para ver tudo funcionando.
Próximos passos
Obviamente, deixamos de fora muitas coisas legais, tanto no Action Cable quanto na SMS API da Nexmo. Não fizemos a autenticação do agente de atendimento ao cliente e não fornecemos uma interface de usuário web para o cliente — o que seria interessante desenvolver com base na API Nexmo Verify , como fizemos na postagem sobre Autenticação de Dois Fatores (2FA) no Ruby on Rails com Devise e Nexmo Verify.
Vou experimentar o o Turbolinks 5 para ver se consigo transformar isso em uma experiência nativa para dispositivos móveis. Adoraria saber o que vocês acrescentariam a seguir. Mandem um tweet para mim (meu nome de usuário é @cbetta) com suas opiniões e ideias.