Встречайте Volt, многообещающую Ruby Framework для динамических приложений
Опубликовано: 2022-03-11Volt — это среда Ruby, разработанная для приложений с большим объемом данных. И серверная, и клиентская стороны написаны на Ruby (который затем компилируется в JS с использованием OPAL), поэтому это позволяет разработчику писать очень динамичные приложения без необходимости писать ни одной строки кода Javascript. Если вы такой же поклонник Ruby, как и я, вам понравится этот фреймворк.
В попытке сделать веб-приложения намного более динамичными, интерфейсные Javascript-фреймворки, такие как Angular.js, Backbone.js и Ember.js, приобрели большую популярность. Однако эти фреймворки часто требуют использования серверного приложения, поэтому они используются в сочетании с веб-фреймворками, такими как Ruby on Rails и Django.
С другой стороны, платформа Ruby Volt способна управлять внутренним и динамическим внешним интерфейсом. Поскольку обе функции тесно интегрированы в его ядро (на самом деле, Volt больше похож на архитектуру MVVM, использующую преимущества привязки данных), он позволяет разработчику быстро создавать эти приложения.
Очень интересная функция, которая поставляется из коробки, — это функция Volt в реальном времени. Если вы когда-либо создавали приложения реального времени, вы знаете, что этот процесс может быть сложным — вы, вероятно, внедрили опрос AJAX, веб-сокеты, события, отправленные сервером (SSE), или даже использовали внешние службы, усложнив приложение и даже понеся дополнительные расходы. . В отличие от других фреймворков, Volt поддерживает активное соединение с сервером (через веб-сокеты), поэтому вместо выполнения Ajax-запросов для каждого действия он мгновенно отправляет изменения всем клиентам. Для этого не требуется никаких настроек.
Использование Volt для создания приложения чата
В этом руководстве по фреймворку Ruby я познакомлю вас с процессом создания приложения реального времени с использованием Volt, а также с тем, что может быть лучше, чем чат-приложение, для демонстрации его возможностей, поскольку чат остается вариантом использования номер один для приложений реального времени.
Прежде всего, давайте установим Volt и MongoDB. Последний процесс подробно описываться не будет:
gem install volt brew install mongodb
mkdir -p /data/db
(создать БД)
chown `id -u` /data/db (change the owner to have the proper dbpath permissions)
Теперь мы готовы создать наше первое приложение, назовем его «чат». Мы можем легко сделать это в пару строк:
volt new chat cd chat
Структура документа имеет некоторое сходство с Rails. Основное отличие, которое заметят пользователи Rails, заключается в том, что у нас есть дополнительная папка внутри приложения, которая содержит остальные папки, такие как активы, контроллеры, модели и представления, эта дополнительная папка является «Компонентом».
Компонент — это изолированная часть приложения. Все страницы внутри компонента отображаются без перезагрузки страницы, поскольку все файлы для этого компонента загружаются с первоначальным http-запросом, поэтому, если мы посетим страницу другого компонента, будет сделан новый http-запрос, и страница будет «перезагружена». '. Для этого примера воспользуемся компонентом по умолчанию, который называется main.
Давайте запустим сервер, выполнив команду «volt server» в консоли, и посмотрим, как он выглядит в браузере, перейдя на localhost:3000:
volt server
Также не забудьте запустить MongoDB в консоли:
mongod
Мы можем заметить, что Volt поставляется с несколькими страницами по умолчанию, включая «Главную» и «О программе». Их можно настроить прямо сейчас.
Еще одна вещь, о которой стоит упомянуть, — это кнопка входа в систему в правом верхнем углу страницы. Volt имеет «пользовательскую» функциональность, интегрированную в платформу через гем «volt-user-templates», который предоставляет способ регистрации и аутентификации пользователей прямо из коробки.
Начиная
Теперь приступим к работе над нашим приложением. Прежде всего, нам не нужна страница «О программе», поэтому мы можем удалить следующее: файл app/main/views/main/about.html
, действие about в app/main/controllers/main_controller.rb
, удалите маршрут /about
в app/main/config/routes.rb
и ссылку навигации в app/main/views/main/main.html
.
<ul class="nav nav-pills pull-right"> <:nav href="/" text="Home" /> <:user-templates:menu /> </ul>
Теперь приступим к делу и начнем с перечисления всех зарегистрированных пользователей:
<: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>
Теперь все зарегистрированные пользователи отображаются на главной странице. Обратите внимание, что код, написанный внутри {{ }}, является кодом Ruby, который выполняется. Таким образом, мы можем перебирать коллекцию пользователей и распечатывать каждую.
Как вы могли заметить, «пользователи» — это имя коллекции, в которой хранятся все пользователи; что следует иметь в виду, так это то, что доступ к атрибутам осуществляется с помощью символа подчеркивания ''
перед именем атрибута. Чтобы это работало, нам сначала нужно добавить строку кода в начало файла main_controller.rb
:
model :store
Volt поставляется с несколькими моделями коллекций, доступными из контроллера, и каждая из них хранит информацию в другом месте. Модель коллекции хранилища хранит данные в хранилище данных, и здесь мы указываем контроллер для использования этого (сейчас поддерживается только одно хранилище данных — MongoDB). Давайте создадим пару пользователей, чтобы посмотреть, как это выглядит.
На данный момент на этой странице нет ничего интересного, мы просто перечисляем зарегистрированных пользователей. Теперь я хотел бы иметь возможность выбрать пользователя для отправки сообщения, удалить имя пользователя, вошедшего в систему, из списка (поскольку он не должен иметь возможность отправлять сообщения самому себе), показать список только для аутентифицированных пользователям и показывать целевую страницу неавторизованным пользователям:
<: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 возвращает текущего (вошедшего в систему) пользователя или ноль.

Атрибут e-click позволяет нам выбрать метод из контроллера, который будет вызываться при щелчке по этому элементу.
Атрибуты и CSS
На самом деле все атрибуты 'e-' являются связывателями событий в Volt, поэтому, например, мы можем добавить e-submit в форму, чтобы выбрать действие, которое будет вызываться на контроллере. Мы собираемся добавить «выбранный» идентификатор пользователя к параметрам, чтобы мы могли знать, какой из них был выбран, и добавить класс с именем «активный», который мы можем позже стилизовать.
Теперь создадим в контроллере метод select_conversation
:
def select_conversation(user) params._user_id = user._id end
Вот и все — если вы снова зайдете на страницу, вы увидите, что URL-адрес меняется каждый раз, когда вы нажимаете на имя пользователя. Кроме того, к этому элементу добавляется класс «активный», поэтому давайте добавим немного CSS, чтобы сделать его видимым (я продолжу и добавлю CSS для элементов, которые мы добавим позже):
.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; } }
Теперь давайте создадим форму справа для отправки сообщений каждому пользователю:
<: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 }}
Во-первых, мы проверяем, выбран ли пользователь перед отображением формы, затем мы отображаем все сообщения из текущего разговора (разговор с выбранным пользователем) из метода в контроллере, который мы собираемся определить чуть позже, а внизу мы показываем форму для отправки новых сообщений.
Обратите внимание, что значение ввода — это атрибут, который мы создаем в модели коллекции страниц, поскольку мы не хотим, чтобы он сохранялся в хранилище данных. Теперь определим методы current_conversation
и send_message
в контроллере:
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
В методе send_message мы добавляем новое сообщение в коллекцию, если сообщение не является пустым (мы проверяем встроенную информацию, поэтому в данный момент нам не нужно возиться с проверками), затем мы устанавливаем для страницы ._new_message to ''
поэтому мы очищаем поле ввода.
Мы также можем добавить эту строку в конец метода select_conversation
. Текущий метод диалога просто запрашивает коллекцию _messages
для сообщений между выбранным пользователем и текущим пользователем.
Завершите работу уведомлениями в реальном времени
В завершение я хотел бы иметь какую-то систему уведомлений, чтобы пользователи могли видеть, когда другие пользователи отправляют им сообщения.
Давайте добавим новую коллекцию под названием _notifications
и создадим новую после отправки каждого сообщения:
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
Кроме того, нам нужно удалять уведомления после того, как пользователь выберет беседу и увидит новые сообщения, поэтому я добавил эту часть в метод select_conversation
.
Давайте добавим счетчик уведомлений прямо рядом с именем пользователя:
<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>
Теперь приложение готово, вы можете открыть пару браузеров и приступить к тестированию возможностей Volt в реальном времени.
Volt определенно стоит попробовать
Несмотря на то, что фреймворк Volt не такой зрелый и надежный, как большинство популярных фреймворков Ruby, которые существуют уже много лет (на данный момент Volt все еще находится в стадии бета-тестирования), его стоит рассмотреть и изучить.
Если вам интересно, воспользуйтесь этим учебным пособием по фреймворку Ruby, чтобы опробовать Volt. Следите за дальнейшими разработками, так как Volt выглядит очень многообещающей средой Ruby даже на этой ранней стадии разработки.
В разработке находится много интересных новых функций, и я почти уверен, что Volt станет более актуальным в течение следующих нескольких лет, поскольку все больше людей начинают с ним экспериментировать. Благодаря ряду инновационных функций, многие разработчики смогли полюбить Volt и использовать его для своего следующего проекта на Ruby.