
Compartilhar:
Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.
Vonage Video Express com Ruby on Rails – Parte 1
Tempo de leitura: 14 minutos
Desde 2004, o Ruby on Rails é muito apreciado por desenvolvedores e, especialmente, por fundadores de startups, por sua capacidade de criar rapidamente aplicativos web completos. Kerry Doyle resumiu perfeitamente a filosofia “Convenção em vez de Configuração” que sustenta o Ruby on Rails: “[ele] busca reduzir o número de decisões que um desenvolvedor que usa a estrutura precisa tomar, sem necessariamente perder a flexibilidade e os princípios de ‘não se repita’ (DRY)”. Essa filosofia torna o Rails ideal para o mentalidade LEAN .
No ano passado, a Vonage lançou Video Express. Essa biblioteca JavaScript, que funciona em conjunto com a Video API da Vonage, funciona como uma extensão do princípio “Convenção em vez de Configuração”, tornando o processo de criação de Applications de videochamadas mais fácil e rápido. Agora, qualquer desenvolvedor pode criar reuniões por vídeo poderosas e robustas sem precisar conhecer todos os detalhes técnicos.
Neste tutorial, vou mostrar como combinar essas tecnologias poderosas para criar um aplicativo full-stack moderno, com todos os recursos de videoconferência que os usuários já esperam encontrar. Vou usar Ruby on Rails, o Vonage Video Express e o novo UI Toolkit da Vonage Vivid.
Este post foi inspirado por “Crie uma festa com Ruby on Rails e a Video API da Vonage”. Vou recriar em grande parte a funcionalidade daquele post e, depois, você verá que foi necessário muito menos código!
O que o aplicativo fará
Em 2020, Ben Greenberg criou um aplicativo para permitir que seu filho assistisse a filmes com os amigos. Esse aplicativo será basicamente o mesmo. Só que eu não assisto a filmes online com amigos. Mas, desde que me mudei para o outro lado do mundo, tem sido difícil encontrar torcedores do meu time favorito de hóquei no gelo, o Blues. Então, em vez de assistir a filmes com meus amigos, adoraria assistir aos jogos dos Blues ou a esportes em geral com amigos da minha cidade natal. Em termos de funcionalidade, o aplicativo é o mesmo e se inspira fortemente no aplicativo de filmes do Ben. Isso facilitará a comparação entre as vantagens e desvantagens de usar o Video Express e programar diretamente na Video API nativa do Vonage Video.
Este aplicativo terá duas páginas: uma página inicial com um formulário de login e uma página de “festa”. Quando os usuários fizerem o login, serão direcionados para uma “Chill Zone” para interagir; lá, serão exibidos em tamanhos iguais. Então, quando o jogo começar, o “moderador”, que é o responsável pela sessão, ativará o compartilhamento de tela para exibir o jogo. No “Modo Assistir”, a tela compartilhada do moderador será a principal e ocupará a maior parte da videochamada. Como a melhor parte de assistir a esportes com amigos são as brincadeiras, ainda poderei ver e ouvir os outros participantes. Mas, se meus amigos estiverem falando alto demais, ainda quero poder silenciá-los. Também permitiremos que os participantes se silenciem, desliguem suas câmeras de Video e selecionem suas entradas e saídas de Video/áudio.
GIF Preview Of Finished Video Conferencing App Built With Vonage Video Express
Na primeira parte, vamos desenvolver o aplicativo em Rails, utilizando alguns componentes do Vivid, e colocar o Video Express em funcionamento. Na segunda parte, vamos dar um passo adiante, criando componentes que combinem as funcionalidades do Video Express com a interface do usuário do Vivid.
Yalla! Vamos lá!
Requisitos
Configuração da Video API da Vonage
A criação de um Account na Video API da Vonage é gratuita. É necessário fazer isso para obter sua chave e seu segredo de API, que são essenciais para que o aplicativo funcione.
Credenciais
Depois de criar um Account na Video API da Vonage, você verá uma interface de painel de controle. O primeiro passo para obter as credenciais da API é criar um novo projeto.
Abra os guia “Projetos” na barra lateral esquerda.
Clique no opção “Criar novo projeto” .
Selecionar Video API da Vonage quando for perguntado que tipo de projeto você deseja criar; Criar projeto personalizado
Insira qualquer nome para o projeto
Escolha a opção do codec VP8. (Mais detalhes sobre a diferença entre o VP8 e o H.264 estão disponíveis aqui)
Agora você tem acesso à chave e ao segredo da API do seu projeto. Guarde-os em um local seguro, pois vamos usá-los em breve.
Ativar o Video Express
Para usar o Video Express, certifique-se de ativar o complemento Video Express no seu Account.
Acesse sua Video API Account e clique em Configurações da conta no menu à esquerda.
Na lista de Complementos da conta, procure Video Express e clique em Adicionar à Account. Em seguida, siga as instruções restantes para ativar o complemento.
Configurando o aplicativo Rails
Antes de podermos adicionar a “magia” do front-end com o Video Express e o Vivid, precisamos fazer alguns ajustes para criar nosso aplicativo Rails e colocá-lo em funcionamento com a Video API da Vonage no back-end.
Instalação
Crie um novo aplicativo Rails usando o PostgreSQL como banco de dados.
rails new video-express-rails --database=postgresql
Comece a trabalhar no projeto: cd video-express-rails
Agora abra o projeto com seu editor de texto preferido.
Dependências do Gem
Precisaremos adicionar duas gems: SDK Ruby da Video API da Vonage (anteriormente conhecida como OpenTok) e dotenv-rails para gerenciar nossas variáveis de ambiente.
Abra o Gemfile e adicione as gems:
gem 'opentok'
gem 'dotenv-rails'Depois de fazer isso, podemos executar bundle install a partir da linha de comando para instalar nossas dependências.
Bibliotecas de JavaScript
Vamos usar duas bibliotecas de JavaScript no front-end: Video Express e Vivid. Antes de usá-las, vamos conhecê-las um pouco melhor.
Video Express
Prometi que o Video Express facilita a vida do desenvolvedor, mas como? Basicamente de duas maneiras: Desempenho e Design.
Desempenho
Video Express' Gerente de Qualidade otimiza continuamente a resolução do stream, a taxa de quadros e os tamanhos de renderização. Isso é muito importante, pois o número de streams em uma sessão clássica de videoconferência cresce exponencialmente! Por exemplo, duas pessoas em uma videochamada geram um fluxo. Seis pessoas em uma videochamada geram 36 fluxos. Mas 25 pessoas em uma videochamada significam que 625 fluxos estão ativos simultaneamente!
O gerente de qualidade trabalha para aumentar ou diminuir a resolução, conforme as redes e as CPUs permitirem, pausar transmissões de vídeo não visíveis e transmissões de áudio com o som desativado, além de solicitar transmissões de vídeo menores aos servidores de mídia quando os vídeos exibidos ficam menores.
Isso pode resultar em uma redução de 60% no uso de largura de banda em sessões com 10 participantes e uma redução de 80% no uso para sessões com 25 participantes!
Design
Desde o início da pandemia da COVID, o mundo se familiarizou profundamente com as videoconferências. A essa altura, todo mundo já sabe, mais ou menos, o que esperar de uma videoconferência e, para a maioria das aplicações, não há necessidade de reinventar a roda. O Video Express faz o trabalho pesado com seu Gerenciador de Layout e Gerenciador de Experiência.
O Gerenciador de Layout controla a adaptabilidade da videochamada, ajustando automaticamente as janelas de vídeo à medida que os participantes saem, entram ou compartilham a tela, além de otimizar as resoluções de vídeo e as taxas de quadros com base no tamanho de renderização.
O Experience Manager define dinamicamente a prioridade dos palestrantes e silencia automaticamente os participantes que entram em reuniões com um número maior de participantes.
Todo esse trabalho árduo significa que o Video Express já vem com uma infinidade de recursos integrados que só precisam ser conectados a uma interface de usuário. O Video Express oferece tudo isso pronto para uso:
Detectar quando os usuários realizam ações como entrar/sair, ativar suas câmeras/áudio
Diferentes opções de layout: grade x alto-falante ativo
Detecção de alto-falante ativo
Como alterar a câmera e o microfone utilizados
Configurando o dispositivo de saída de áudio
Criação de um editor de visualização
Acesso ao áudio/Video do apresentador que está compartilhando a tela
Detectar quando outros clientes publicam transmissões de compartilhamento de tela
Ativar e desativar o áudio e o Video de um participante que está compartilhando a tela
Vívido
Como eu disse, o Video Express já conta com toda a funcionalidade do front-end pronta; só precisa de um desenvolvedor para criar uma interface de usuário para o usuário final. A Vonage faz isso! Temos desenvolvido um excelente kit de ferramentas de interface de usuário chamado Vivid, que agiliza muito a criação de Applications com recursos de comunicação.
O Vivid foi desenvolvido usando Web Components, por isso funciona em qualquer framework ou mesmo em HTML/JS puro, como o Rails. E tem uma aparência ótima! Além disso, é acessíveis na web!
Instalação do Vivid
Vamos instalar o Vivid e começar:
yarn add @vonage/vivid
Geração de modelos
A seguir, vamos gerar um modelo para armazenar e manipular as informações da sessão de exibição em grupo. Isso também criará uma watch_parties em nosso banco de dados. Para conectar os usuários à mesma videochamada, precisaremos passar à Video API da Vonage o session_id. Na linha de comando, execute o seguinte:
rails g model WatchParty session_id:string
Antes de executarmos a migração para criar essa coluna em nosso banco de dados, precisaremos atualizar a migração para garantir que as sessões não sejam definidas como nulas por padrão quando for necessário recuperá-las.
Abra o db/migrate diretório e localize o arquivo chamado: TIMESTAMP_create_watch_parties.rb
//In TIMESTAMP_create_watch_parties.rb
class CreateWatchParties < ActiveRecord::Migration[6.1]
def change
create_table :watch_parties do |t|
t.string :session_id, null:false
t.boolean :expired, default: false
t.timestamps
end
end
endAgora você pode aplicar essa migração do banco de dados ao esquema executando o seguinte comando na linha de comando:
rails db:create db:migrate
Este comando criará o banco de dados PostgreSQL e a tabela “sessions”, com a coluna “session_id”.
Criação dos métodos da classe
Agora, vamos implementar nossa lógica de “watch party”, que utilizará a Video API da Vonage para conectar os usuários a uma sessão de videochamada.
Cada sessão do Vonage Video possui um ID de sessão exclusivo. Esse ID de sessão é o que permite que diferentes participantes entrem no mesmo bate-papo por vídeo. Além disso, cada participante do bate-papo por vídeo precisa de um token que lhes permita participar. Um token pode receber permissões especiais, como recursos de moderação.
No modelo Session, vamos criar três métodos de classe que serão usados para criar um novo ID de sessão ou carregar o anterior, além de gerar tokens para cada participante.
Saiba mais sobre Sessões da Video API da Vonage.
Abrir app/models/watch_party.rb
Primeiro, precisamos acessar a funcionalidade da Video API da Vonage criando uma instância do SDK do OpenTok para Ruby. Passaremos nossa API_KEY e API_SECRET, da seção de credenciais acima, por meio das variáveis de ambiente ENV
require 'opentok'
@opentok = OpenTok::OpenTok.new(ENV['OPENTOK_API_KEY'], ENV['OPENTOK_API_SECRET'])Agora podemos adicionar esses métodos à classe. O método Session#create_or_load_session_id verificará se já existe um ID de sessão. Se houver um ID, ele será utilizado. Caso contrário, será gerado um novo.
def self.create_or_load_session_id
unless WatchParty.any?
return @session_id = create_new_session
else
last_session = WatchParty.last
if last_session
@session_id = last_session.session_id
elsif !last_session
@session_id = create_new_session
else
raise 'Something went wrong with the session creation!'
end
end
endO método acima também faz referência a um método adicional que precisamos criar, chamado create_new_session que se encarrega de criar uma nova sessão caso ainda não exista uma:
def
session = @opentok.create_session
@session_id = session.session_id
endPor fim, vamos criar um método que atribuirá o token correto a cada participante:
def self.create_token(session_id)
@token = @opentok.generate_token(session_id)
endSeu modelo completo do WatchParty deve ficar assim:
class WatchParty < ApplicationRecord
require 'opentok'
@opentok = OpenTok::OpenTok.new ENV['OPENTOK_API_KEY'], ENV['OPENTOK_API_SECRET']
def self.create_or_load_session_id
if WatchParty.any?
last_session = WatchParty.last
if last_session && last_session.expired == false
@session_id = last_session.session_id
@session_id
elsif (last_session && last_session.expired == true) || !last_session
@session_id = create_new_session
else
raise 'Something went wrong with the session creation!'
end
else
@session_id = create_new_session
end
end
def self.create_new_session
session = @opentok.create_session
@session_id = session.session_id
end
def self.create_token(user_name, moderator_name, session_id)
@token = user_name == moderator_name ? @opentok.generate_token(session_id, { role: :moderator }) : @opentok.generate_token(session_id)
end
end
Definindo nossas variáveis de ambiente
Vimos que a lógica da nossa Video API exige o uso de algumas variáveis de ambiente confidenciais. Vamos defini-las agora.
Crie o .env arquivo na raiz do video-express projeto:
touch .env
No interior, definamos nossas variáveis ENV:
OPENTOK_API_KEY=''
OPENTOK_API_SECRET=''
MODERATOR_NAME=''
PARTY_PASSWORD=''Aqui, você precisará inserir as credenciais da Video API mencionadas acima. Em um aplicativo real, seria recomendável armazenar as informações sobre os moderadores e as senhas das sessões de exibição em grupo no banco de dados, mas, para esta demonstração, basta armazená-las em uma variável de ambiente!
Não se esqueça de adicionar um MODERATOR_NAME e PARTY_PASSWORDpara usar na página de login.
Definindo as rotas
O usuário verá duas páginas: a página inicial e a página de festas. Mas também precisamos coletar as informações do formulário de login para verificar se a senha está correta e se o usuário é o moderador. Portanto, criaremos duas solicitações GET e uma POST:
Rails.application.routes.draw do
get '/', to: 'watch_party#home'
get '/party', to: 'watch_party#party'
post '/login', to: 'watch_party#login'
end Criação do controlador
Com o princípio do Rails “Convenção em vez de configuração”, já sabemos quais ações precisaremos para nosso controlador, assim como as rotas!
Na linha de comando, gere o controlador WatchParty com as ações home, login e party.
rails g controller WatchParty home login party
O gerador do Rails vai criar algumas coisas extras que não queremos. Então, agora vá e exclua as rotas que ele gerou em
app/config/routes.rb. E exclua completamente o arquivo de visualização do login;app/views/watch_party/login.html.erb
Nesta fase, com toda a configuração e preparação principais já concluídas, prefiro trabalhar com um par de ação/visualização de cada vez até terminar o aplicativo.
Criação da página inicial
A página inicial que queremos criar terá a seguinte aparência:
Watch Party Home Page
Se consultarmos a documentação do Vivid, veremos que temos todos os componentes de que precisamos:
Então, com um pouco da magia do Rails e um pouco da magia do Vivid, temos tudo o que precisamos. Há apenas duas coisas complicadas aqui. Primeiro, você vai perceber que os cartões podem ter títulos e subtítulos no Vivid. Então, por que precisamos usar o componente vwc-text? Porque o Vivid utiliza slots em seus componentes web e, ao usar o slot="main" para inserir conteúdo no cartão, isso substitui os slots do título e do subtítulo.
Em segundo lugar, o formulário não nos ajuda a enviar os dados para o servidor. Por isso, precisamos usar o helper do Rails form_with. No total, fica assim:
<div class="card-wrapper">
<vwc-card>
<div slot="main" id="box">
<vwc-text font-face="subtitle-1" >Big Game Watch Party
<br>
<span><vwc-text font-face="body-1-code">Built With Vonage Video Express on Rails</vwc-text></span></vwc-text>
<%= form_with(url: "/login", method: "post") do %>
<vwc-textfield name="name" label="Enter Your Name" icon="user" outlined="">
</vwc-textfield>
<vwc-textfield name="password" label="Enter Team Passcode" icon="lock" type="password" outlined="">
</vwc-textfield>
<div class="controls">
<vwc-button layout="outlined" type="reset" outlined="">
Reset
</vwc-button>
<vwc-button layout="filled" type="submit" unelevated="">
Submit
</vwc-button>
</div>
<% end %>
</div>
</vwc-card>
</div>
Então, agora, se iniciarmos nosso servidor, deveríamos ter uma bela página inicial, como na imagem, certo? Experimente! Execute rails s na linha de comando e abra localhost:3000 no seu navegador.
Eita, não funciona!
Porque, embora tenhamos o Vivid em nosso projeto, ainda não o importamos no código para usá-lo. Então, agora vamos fazer isso no nosso JavaScript. Em app/javascript/packs/application.js adicionar esta linha abaixo de import "channels:
import '@vonage/vivid';
Agora, se você abrir a página, ela vai funcionar. Mas ainda está bem feia. Então, vamos dar um estilo a ela. Em app/assets/stylesheets/watch_party.scss vamos adicionar um pouco de CSS:
// Home Page Styles
.card-wrapper {
display: flex;
}
vwc-card {
margin: auto;
padding: 10%;
}
#box {
padding: 50px 100px;
}
form {
display: grid;
gap: 20px;
}
.controls {
display: flex;
justify-content: flex-end;
gap: 10px;
}Antes de continuarmos, vamos adicionar o lindo plano de fundo da Vonage em app/assets/stylesheets/application.scss
body {
background: linear-gradient(90deg, #9DD2FE 4.86%, #8728FB 96.11%);
margin: 0px;
} Definindo o login
Temos um formulário, mas queremos garantir que apenas os verdadeiros fãs — ou seja, nossos amigos — possam participar da nossa sessão de cinema! Por isso, vamos adicionar um pouco da lógica do Rails Strong Parameters para detectar o name e password dos parâmetros enviados no formulário da página inicial.
class WatchPartyController < ApplicationController
def home
end
def login
@name = login_params[:name]
if login_params[:password] == ENV['PARTY_PASSWORD']
redirect_to party_path(name: @name)
else
redirect_to('/', flash: { error: 'Incorrect password' })
end
end
def party
end
private
def login_params
params.permit(:name, :password, :authenticity_token, :commit)
end
end
Os logins bem-sucedidos redirecionarão para o party_path. Esse caminho levará os usuários à página da festa, o coração do aplicativo, onde ficará nossa sala do Video Express. Vamos criá-la!
Criando a página do partido
Primeiro, vamos dar uma olhada no que estamos desenvolvendo. Esta é a página “Party” no “Chill Mode”, vista por um usuário que não é moderador. Mas, para a Parte 1, não vamos nos preocupar com os componentes do cabeçalho nem da barra de ferramentas; portanto, só nos resta desenvolver o bate-papo por Video.
Party Page: Chill Mode, Non Moderator
Vamos começar pela estrutura básica da página, o HTML. Temos três componentes: um cabeçalho, a chamada de Video e uma barra de ferramentas. Mas, por enquanto, vamos apenas deixar comentários onde está o header e toolbar serão colocados: Adicione isso ao seu app/views/video/party.html.erb:
<header>
<!-- Header Will Go Here -->
</header>
<main class="app">
<!-- Video Chat Will Go Here -->
<toolbar class="toolbar-wrapper">
<!-- Toolbar Will Go Here -->
</toolbar>
</main>Então, agora só falta adicionar nossa videochamada com o Video Express na página da festa. Vamos criar isso agora.
Criando uma sala com o Video Express
A Video API da Vonage oferece aos desenvolvedores controle total sobre a personalização do layout de vídeo por meio da manipulação publisher e subscriber elementos. No Video Express, esses são substituídos pelo conceito de um room. Adicioná-lo é tão fácil quanto 1, 2, 3.
Inclua a biblioteca. Adicione este script no início do arquivo:
<script src="https://static.opentok.com/v1/js/video-express.js"></script>Agora, crie a sala usando o código de exemplo da documentação do Video Express. Observe que passamos o parâmetro adicional
participantName. O Video Express é leve, mas oferece algumas opções; explore a documentação!
<script>
const room = new VideoExpress.Room({
apiKey: '<%= @api_key %>', // add your OpenTok API key
sessionId: '<%= @session_id %>', // add your OpenTok Session ID
token: '<%= @token %>', // add your OpenTok token
roomContainer: 'roomContainer',
participantName: '<%= @name %>'
});
room.join();
</script>Podemos ver que o `roomContainer` está procurando o ponto de entrada no HTML onde se fixar e incorporar o `Room`. Portanto, precisamos criar um elemento com o id
roomContainter.
O código final do party.html.erb fica assim:
<script src="https://static.opentok.com/v1/js/video-express.js"></script>
<header>
<!-- Header Will Go Here -->
</header>
<main class="app">
<div id="roomContainer"></div>
<toolbar>
<!-- Toolbar Will Go Here -->
</toolbar>
</main>
<script>
const room = new VideoExpress.Room({
apiKey: '<%= @api_key %>', // add your OpenTok API key
sessionId: '<%= @session_id %>', // add your OpenTok Session ID
token: '<%= @token %>', // add your OpenTok token
roomContainer: 'roomContainer',
participantName: '<%= @name %>'
});
room.join();
</script>Então, agora já devemos conseguir executar nosso servidor e ver um belo site de videochamadas, certo? Você já deve saber que a resposta é “não” 😆. O que está faltando? Bem, ainda não usamos nenhuma daquela lógica do OpenTok da Video API para enviar para o Video Express.
Portanto, precisamos definir nossas variáveis do OpenTok no WatchParty Controller e passá-las para o nosso front-end.
No WatchParty Controller, precisamos adicionar a set_opentok_vars ação"
def set_opentok_vars
@api_key = ENV['OPENTOK_API_KEY']
@api_secret = ENV['OPENTOK_API_SECRET']
@session_id = WatchParty.create_or_load_session_id
@moderator_name = ENV['MODERATOR_NAME']
@name ||= params[:name]
@token = WatchParty.create_token(@name, @moderator_name, @session_id)
endVamos usar o before_action que chamará o método antes de entrar na party ação. Assim, o Controlador completo fica assim:
class WatchPartyController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :set_opentok_vars
def home
end
def login
@name = login_params[:name]
if login_params[:password] == ENV['PARTY_PASSWORD']
redirect_to party_path(name: @name)
else
redirect_to('/', flash: { error: 'Incorrect password' })
end
end
def party
end
private
def set_opentok_vars
@api_key = ENV['OPENTOK_API_KEY']
@api_secret = ENV['OPENTOK_API_SECRET']
@session_id = WatchParty.create_or_load_session_id
@moderator_name = ENV['MODERATOR_NAME']
@name ||= params[:name]
@token = WatchParty.create_token(@name, @moderator_name, @session_id)
end
def login_params
params.permit(:name, :password, :authenticity_token, :commit)
end
end
Agora, se atualizarmos a página… vemos que nossa câmera liga e o áudio fica todo estranho. Mas nada aparece na tela. Por quê?! O Video Express está funcionando e estamos conectados a uma sessão de vídeo por meio da Video API. Mas não reservamos espaço algum na tela para o vídeo aparecer!
Vamos adicionar um pouco de CSS do modelo padrão do Video Express para a tela de vídeo. Selecionamos o elemento #roomContainer e definimos largura e altura totais para ele, excluindo o cabeçalho. Também adicionamos um pouco de CSS para indicar ao Video Express onde exibir a visualização local e o compartilhamento de tela quando forem acionados.
// Video Express Styles
#roomContainer {
width: 100vw;
height: calc(100vh - 130px);
position: relative;
}
#roomContainer > .OT_publisher {
top: 25px;
right: 25px;
position: absolute;
border-radius: 10px;
}
#roomContainer > .OT_screenshare {
top: 25px;
left: 25px;
position: absolute;
border-radius: 10px;
}
Uau! Agora temos uma sessão de Video. Tente participar usando várias abas ou nomes diferentes. Uau! Você já tem videoconferência no Rails!
Próximos passos
Na Parte 2, vamos adicionar algumas das funcionalidades que você esperaria encontrar em um sistema moderno de videoconferência:
Compartilhamento de tela: o acesso será restrito de forma que apenas nosso moderador possa utilizá-lo
Silenciar todos os outros participantes
Silenciar o microfone
Esconda-se (desligue a câmera)
Selecionar entradas: microfone e câmera
Selecionar saída de áudio
Faremos isso adicionando mais componentes do Vivid e incorporando um pouco de JavaScript do Video Express.
Se você chegou até aqui, ótimo trabalho! Entre em contato comigo no Twitter e me conte o que achou do tutorial.
Compartilhar:
Benjamin Aronov is a developer advocate at Vonage. He is a proven community builder with a background in Ruby on Rails. Benjamin enjoys the beaches of Tel Aviv which he calls home. His Tel Aviv base allows him to meet and learn from some of the world's best startup founders. Outside of tech, Benjamin loves traveling the world in search of the perfect pain au chocolat.