Хранение данных между перезапусками веб-приложения
Метод Kernel#at_exit
Метод Kernel#at_exit
позволяет зарегистрировать блок кода, который будет вызван при выключении приложения. Причём данный метод может быть вызван несколько раз и для каждого вызова будет зарегистрирован свой обработчик.
Документация
Задача
Создайте простое приложение, которое будет добавлять несколько обработчиков на окончание приложения.
- Первый обработчик должен считывать содержимое текущего файла в строку.
- Второй обработчик должен выводить считанное содержимое на стандартный вывод.
Подсказка
- Переменная
__FILE__
содержит в себе путь к текущему Ruby-файлу. - Метод
File.read
позволяет считать содержимое всего файла в строку.
Хранилище PStore
Мы ранее рассматривали текстовые файлы в формате CSV и YAML для сохранения данных приложения между запусками. Их использование требует от вас написать собственные преобразования из текста в свои структуры данных. Хранилище PStore позволяет сохранить Ruby-объект в файле, а затем считать информацию из него. Базовым элементом хранилища является хеш-объект, а данными могут выступать любые объекты.
Для сохранения объектов применяется механизм, предоставляемый модулем Marshal
. Данный модуль преобразует объекты Ruby в набор байт и обратно. Если ваш объект «плохо» преобразуется в набор байт, то вы можете определить специальные методы-помошники, которые будут преобразовывать ваш объект в стандартную структуру и обратно из неё.
Документация
Задача
Разработайте простое консольное приложение, которое позволит пользователю оперировать набором оценок. Каждая оценка описывается тремя параметрами: курс, задание, оценка. Первые два являются строками, а последняя - вещественное число от 0 до 5.
Приложение должно показывать пользователю текущий список оценок, позволять добавлять новую оценку в конец списка и выходить из приложения.
- Создайте класс, описывающий одну оценку.
- Создайте класс, описывающий дневник, содержащий все оценки. Данный класс должен иметь методы для добавления новой оценки, получения списка оценок и итератор для обхода данного списка.
- Приложение должно хранить информацию об оценках в PStore. При запуске приложения данные из хранилища должны считываться, а при выходе записываться в хранилище. Рекомендуется создать отдельные методы, которые смогут успешно считывать и записывать информацию об оценках в хранилище.
Надёжное хранение данных в Sinatra-приложениях
Ввиду того, что при создании приложений на Sinatra у вас нет возможности отследить время окончания работы самого приложения напрямую, необходимо использовать обработчик окончания приложения at_exit
. Однако, если вы поместите его не в правильное место, то он не будет корректно работать.
Причиной этого поведения является собственный обработчик at_exit
, который Sinatra
использует для запуска приложения. Данный обработчик расположен в файле sinatra
, который мы подключаем в самом начале наших приложений. Если вы разместите обработчик at_exit
после подключения данного файла, то он отработает до старта Sinatra-приложения, что не позволит выполнить код во время выключения основного приложения.
В результате для успешной обработки данного сигнала необходимо:
- Создать переменную, в которой будет храниться ссылка на хранилище данных.
- Создать собственный обработчик сигнала
at_exit
в самом начале файла, где вы разрабатываете приложение. В обработчик поместить сохранение данных, которые сейчас находятся в хранилище. - Подключить
sinatra
к приложению. Для разработки следует также подключить и Sinatra-Reloader. - Добавить ссылку на хранилище в конфигурацию
Sinatra
. Данное хранилище следует использовать во время работы приложения.
Задача
Переработайте предыдущее приложение в веб-приложение на основе Sinatra. Приложение должно содержать 2 страницы: отображение текущего списка оценок и добавление новой оценки. После завершения работы приложения из консоли (с помощью комбинации клавиш Ctrl+C) приложение должно сохранять данные в хранилище PStore. То есть после перезапуска данные должны успешно сохраняться.
Дополнительно. Добейтесь того, чтобы приложение было полностью функционально при запуске как консольное и как веб-приложение. Для решения этой задачи вам потребуется создать 2 независимых стартовых Ruby-скрипта. Первый скрипт будет запускать веб-приложение, а второй - консольное.