Метод 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-приложения, что не позволит выполнить код во время выключения основного приложения.

В результате для успешной обработки данного сигнала необходимо:

  1. Создать переменную, в которой будет храниться ссылка на хранилище данных.
  2. Создать собственный обработчик сигнала at_exit в самом начале файла, где вы разрабатываете приложение. В обработчик поместить сохранение данных, которые сейчас находятся в хранилище.
  3. Подключить sinatra к приложению. Для разработки следует также подключить и Sinatra-Reloader.
  4. Добавить ссылку на хранилище в конфигурацию Sinatra. Данное хранилище следует использовать во время работы приложения.

Задача

Переработайте предыдущее приложение в веб-приложение на основе Sinatra. Приложение должно содержать 2 страницы: отображение текущего списка оценок и добавление новой оценки. После завершения работы приложения из консоли (с помощью комбинации клавиш Ctrl+C) приложение должно сохранять данные в хранилище PStore. То есть после перезапуска данные должны успешно сохраняться.

Дополнительно. Добейтесь того, чтобы приложение было полностью функционально при запуске как консольное и как веб-приложение. Для решения этой задачи вам потребуется создать 2 независимых стартовых Ruby-скрипта. Первый скрипт будет запускать веб-приложение, а второй - консольное.