Conheça o Volt, um framework Ruby promissor para aplicativos dinâmicos
Publicados: 2022-03-11Volt é uma estrutura Ruby projetada para aplicativos ricos em dados. Ambos os lados do servidor e do cliente são escritos em Ruby (que é então compilado para JS usando OPAL), então isso permite que o desenvolvedor escreva aplicativos muito dinâmicos sem ter que escrever uma única linha de código Javascript. Se você é um fã de Ruby como eu, vai adorar este framework.
Na tentativa de tornar as aplicações web muito mais dinâmicas, frameworks Javascript front-end como Angular.js, Backbone.js e Ember.js ganharam muita popularidade. No entanto, esses frameworks geralmente requerem um aplicativo de back-end para serem úteis, então eles são usados em conjunto com frameworks da web como Ruby on Rails e Django.
Por outro lado, o framework Ruby Volt é capaz de gerenciar o back-end e um front-end dinâmico. Como ambas as funcionalidades estão fortemente integradas ao seu núcleo (na verdade, o Volt é mais como uma arquitetura MVVM, aproveitando as vantagens das ligações de dados), ele permite que o desenvolvedor construa esses aplicativos rapidamente.
Um recurso muito legal que sai da caixa é o recurso em tempo real do Volt. Se você já fez aplicações em tempo real, sabe que o processo pode ser desafiador – você provavelmente implementou AJAX-polling, web sockets, Server-Sent Events (SSE) ou até mesmo serviços externos usados, adicionando complexidade à aplicação e até mesmo incorrendo em custos adicionais . Ao contrário de outros frameworks, o Volt mantém uma conexão com o servidor ativa (via web sockets), então ao invés de fazer requisições Ajax para cada ação, ele envia as mudanças instantaneamente para todos os clientes. Nenhuma configuração é necessária para que isso funcione.
Usando Volt para criar um aplicativo de bate-papo
Neste tutorial do framework Ruby, vou guiá-lo pelo processo de criação de um aplicativo em tempo real usando Volt, e nada melhor do que um aplicativo de bate-papo para demonstrar seus recursos, já que o bate-papo continua sendo o caso de uso número um dos aplicativos de tempo real.
Antes de tudo, vamos instalar o Volt e o MongoDB. Este último processo não será abordado em detalhes:
gem install volt brew install mongodb
mkdir -p /data/db
(criar caminho de banco de dados)
chown `id -u` /data/db (change the owner to have the proper dbpath permissions)
Agora estamos prontos para criar nosso primeiro aplicativo, vamos chamá-lo de 'chat'. Podemos fazer isso facilmente em algumas linhas:
volt new chat cd chat
A estrutura do documento tem algumas semelhanças com Rails. A principal diferença que os usuários do Rails vão notar é que temos uma pasta extra dentro do app que contém o resto das pastas como assets, controllers, models e views, essa pasta extra é um 'Component'.
Um Componente é uma seção isolada do aplicativo. Todas as páginas dentro de um componente são renderizadas sem recarregar a página, pois todos os arquivos desse componente são carregados com a solicitação http inicial, portanto, se visitarmos uma página de um componente diferente, uma nova solicitação http será feita e a página será 'recarregada '. Para este exemplo vamos usar o componente padrão chamado 'main'.
Vamos iniciar o servidor executando o comando 'volt server' no console e ver como ele fica no navegador navegando até localhost:3000:
volt server
Também não se esqueça de iniciar o MongoDB no console:
mongod
Podemos notar que o Volt vem com várias páginas padrão, incluindo 'Home' e 'About'. Estes podem ser personalizados imediatamente.
Outra coisa que vale a pena mencionar é o botão de login no canto superior direito da página. O Volt tem uma funcionalidade de “usuário” integrada ao framework através da gem 'volt-user-templates', que fornece uma maneira de registrar e autenticar usuários, imediatamente.
Começando
Agora, vamos começar a trabalhar em nosso aplicativo. Em primeiro lugar, não precisamos da página 'Sobre' para que possamos excluir o seguinte: O arquivo app/main/views/main/about.html
, a ação about em app/main/controllers/main_controller.rb
, remova a rota /about
em app/main/config/routes.rb
e o link nav em app/main/views/main/main.html
.
<ul class="nav nav-pills pull-right"> <:nav href="/" text="Home" /> <:user-templates:menu /> </ul>
Agora vamos ao que interessa e comece listando todos os usuários registrados:
<:Body> <h1>Home</h1> <div class="row"> <div class="col-md-4"> {{ _users.each do |user| }} <div class="contact"> {{user._name}} </div> {{ end }} </div> </div>
Agora todos os usuários registrados estão sendo listados na página inicial. Observe que o código escrito dentro de {{ }} é um código Ruby que é executado. Dessa forma, podemos iterar sobre a coleção de usuários e imprimir cada uma.
Como você deve ter notado, 'usuários' é o nome da coleção onde todos os usuários estão armazenados; algo a ter em mente é que os atributos são acessados com um sublinhado ''
prefixado ao nome do atributo. Para que isso funcione, primeiro precisamos adicionar uma linha de código no topo do arquivo main_controller.rb
:
model :store
O Volt vem com vários modelos de coleta acessíveis a partir do controlador, e cada um deles armazena as informações em um local diferente. O modelo de coleção de armazenamento armazena os dados no armazenamento de dados, e aqui estamos especificando o controlador para usar esse (no momento, o único armazenamento de dados suportado é o MongoDB). Vamos criar alguns usuários para ver como fica.
No momento não há nada de excitante nesta página, estamos apenas listando os usuários registrados. Agora eu gostaria de poder selecionar um usuário para enviar uma mensagem, remover o nome do usuário logado no momento da lista (já que ele não deve enviar mensagens para si mesmo), mostrar a lista apenas para autenticados usuários e mostrar uma página de 'landing' para usuários não autenticados:
<:Body> <h1>Home</h1> {{ if Volt.user }} <div class="row"> <div class="col-md-4"> {{ _users.each do |user| }} {{ if user._id != Volt.user._id }} <div class="contact {{ if params._user_id == user._id }} active {{ end }}" e-click="select_conversation(user)"> {{user._name}} </div> {{ end }} {{ end }} </div> </div> {{ else }} <p>This is a sample application built with Volt to demonstrate its real-time capabilities. Please log in to access it.</p> {{ end }}
Volt.user retorna o usuário atual (conectado) ou nil.

O atributo e-click nos permite selecionar um método do controller que será chamado quando aquele elemento for clicado.
Atributos e CSS
Na verdade, todos os atributos 'e-' são event binders no Volt, então por exemplo podemos adicionar e-submit a um formulário para escolher a ação que será chamada no controller. Vamos adicionar o ID do usuário 'selecionado' aos parâmetros para que possamos saber qual foi selecionado e adicionar uma classe chamada 'ativo' que podemos estilizar posteriormente.
Agora vamos criar o método select_conversation
no controller:
def select_conversation(user) params._user_id = user._id end
E é isso – se você verificar a página novamente, poderá ver que a URL muda toda vez que você clica no nome de um usuário. Além disso, a classe 'active' está sendo adicionada a esse elemento, então vamos adicionar um pouco de CSS para torná-lo visível (vou adicionar o CSS para itens que adicionaremos mais tarde):
.conversation{ form{ input{ margin: 10px 0 5px 0; } } }
.contact{ width:100%; padding:5px; margin: 4px 0; font-size:15px; cursor:pointer; &:hover{ background-color: #FAFAFA; } &.active{ background-color: #337ab7; color: #FFF; } .badge{ background-color: #900; } }
.message{ max-width: 80%; padding:10px 15px; margin: 5px 0; background-color: #FEFEFE; border: 1px solid #E7E7E7; border-radius: 5px; float: left; clear:both; &.sent{ background-color: #E4F3DB; border: 1px solid #B7D0A7; float: right; } p{ margin:0; } }
Agora vamos criar um formulário do lado direito para enviar mensagens para cada usuário:
<:Body> <h1>Home</h1> {{ if Volt.user }} <div class="row"> <div class="col-md-4"> {{ _users.each do |user| }} {{ if user._id != Volt.user._id }} <div class="contact {{ if params._user_id == user._id }} active {{ end }}" e-click="select_conversation(user)"> {{user._name}} </div> {{ end }} {{ end }} </div> {{ if params._user_id }} <div class="col-md-8 well conversation"> {{ current_conversation.each do |message| }} <div class="message {{ if message._sender_id == Volt.user._id }} sent {{ end }}"> <p>{{ message._text }}</p> </div> {{ end }} {{ if current_conversation.count == 0 }} <p>You have no messages yet. Start chatting!</p> {{ else }} <div class="clearfix"></div> {{ end }} <form e-submit="send_message" role="form"> <div class="form-group"> <input class="form-control" type="text" placeholder="Write a message" value="{{ page._new_message }}" /> <button type="submit" class="btn btn-primary pull-right">Submit</button> </div> </form> </div> {{ end }} </div> {{ else }} <p>This is a sample application built with Volt to demonstrate its real-time capabilities. Please log in to access it.</p> {{ end }}
Primeiro, verificamos se há um usuário selecionado antes de exibir o formulário, depois exibimos todas as mensagens da conversa atual (a conversa com o usuário selecionado) de um método no controlador que vamos definir daqui a pouco, e na parte inferior estamos exibindo um formulário para envio de novas mensagens.
Observe que o valor da entrada é um atributo que estamos criando no modelo de coleção de páginas, pois não queremos que ele seja armazenado no armazenamento de dados. Agora vamos definir os métodos current_conversation
e send_message
no controller:
def send_message unless page._new_message.strip.empty? _messages << { sender_id: Volt.user._id, receiver_id: params._user_id, text: page._new_message } page._new_message = '' end end def current_conversation _messages.find({ "$or" => [{ sender_id: Volt.user._id, receiver_id: params._user_id }, { sender_id: params._user_id, receiver_id: Volt.user._id }] }) end
No método send_message adicionamos uma nova mensagem à coleção se a mensagem não estiver em branco (estamos checando inline para não ter que mexer com validações no momento), então configuramos a página ._new_message to ''
então esvaziamos o campo de entrada.
Podemos querer adicionar essa linha ao final do método select_conversation
também. O método de conversação atual apenas consulta a coleção _messages
para mensagens entre o usuário selecionado e o usuário atual.
Finalize com notificações em tempo real
Para finalizar, gostaria de ter algum tipo de sistema de notificação, para que os usuários possam ver quando outros usuários estão enviando mensagens para eles.
Vamos adicionar uma nova coleção chamada _notifications
e criar uma nova após cada mensagem ser enviada:
def send_message unless page._new_message.strip.empty? _messages << { sender_id: Volt.user._id, receiver_id: params._user_id, text: page._new_message } _notifications << { sender_id: Volt.user._id, receiver_id: params._user_id } page._new_message = '' end end def select_conversation(user) params._user_id = user._id unread_notifications_from(user).then do |results| results.each do |notification| _notifications.delete(notification) end end page._new_message = '' end def unread_notifications_from(user) _notifications.find({ sender_id: user._id, receiver_id: Volt.user._id }) end
Além disso, precisamos excluir as notificações depois que um usuário seleciona a conversa e vê as novas mensagens, então adicionei essa parte ao método select_conversation
.
Vamos adicionar um contador de notificações ao lado do nome de usuário:
<div class="contact {{ if params._user_id == user._id }} active {{ end }}" e-click="select_conversation(user)"> {{user._name}} {{ if unread_notifications_from(user).count > 0 }} <span class="badge"> {{ unread_notifications_from(user).count }} </span> {{ end }} </div>
Agora que o aplicativo está pronto, você pode abrir alguns navegadores e começar a testar os recursos em tempo real do Volt.
Definitivamente vale a pena tentar o Volt
Mesmo que o framework Volt não seja tão maduro e robusto quanto a maioria dos frameworks Ruby populares que existem há anos (no momento o Volt ainda está em beta), vale a pena considerar e estudar.
Caso você esteja interessado, use este tutorial do framework Ruby para dar uma volta no Volt. Fique de olho nos desenvolvimentos futuros, pois o Volt parece um framework Ruby muito promissor, mesmo neste estágio inicial de desenvolvimento.
Há muitos novos recursos interessantes no pipeline e tenho certeza de que o Volt se tornará mais relevante nos próximos dois anos, à medida que mais pessoas começarem a experimentá-lo. Devido a uma série de recursos inovadores, muitos desenvolvedores podem se apaixonar pelo Volt e usá-lo em seu próximo projeto Ruby.