Когда вы создаёте веб-приложние, то зачастую оно предназначено для обслуживания большого количества пользователей одновременно. Рассмотрим основные типы страниц, что мы можем встретить в веб-приложении:

  • Страницы с информации, которые не содержат данные пользователей:
    • Статические страницы.
    • Страницы со статистической информацией.
    • Списки данных без фильтров.
  • Страницы с персонализированной информацией.
    • Страницы, в которые пользователь вводит данные.
    • Страницы с персональной информацией пользователя: личный кабинет, корзина и т.п.
    • Страницы с общедоступной информацией, на которую можно накладывать фильтры.

Для отображения страниц из первой категории достаточно получить информацию из постоянного хранилища данных и передать их на страницу. Для второй категории потребуются дополнительные данные, которые могут включать в себя:

  • Данные, которые ввёл пользователь на форме.
  • Данные, которые переданы как параметры запроса.
  • Данные, которые ввёл пользователь ранее при работе с сайтом.

Параметры запроса

Рассмотрим как можно передавать данные в контроллер в качестве параметра запросов.

Их указывают в качестве последнего элемента запроса и отделяют их от ресурса с помощью знака вопроса. Формат указания параметров следующий:

ресурс?параметр1=значение1&параметр2=значение2, где

  • ресурс - путь конкретному веб-ресурсу, например, http://server.com/resource.
  • ? - обязательный разделитель между ресурсом и параметрами.
  • параметр1=значение1 - пара, описывающая один параметр. Текст до знака равенства описывает название параметра, которое можно будет использовать в приложении. Текст после знака равенства описывает значение данного параметра.
  • & - обязательный разделитель между парами, описывающими один параметр.

Рассмотрим пример запроса:

https://localhost:8573/users?sex=female&salary=gt500&page=10

  • Путь к ресурсу: https://localhost:5873/users. Данный ресурс, видимо, описывает пользователей.
  • Параметры запроса:
    • sex = female, пол пользователя - женский.
    • salary = gt500, заработная плата, возможно, больше 500.
    • page = 10, страница списка - 10.

В контроллере Sinatra для обработки параметров достаточно воспользоваться переменной params. То есть для контроллера нет различий между параметрами, которые передаются от формы или в параметрах запроса. В качестве ключей данного хеша используются имена параметров, которые перадаются в рамках запроса.

Сессии

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

Однако для ряда данных этого недостаточно. В частности для процедуры аутентификации необходимо выполнить следующие шаги:

  1. Получить от пользователя имя пользователя и пароль. Передавать эти данные можно ТОЛЬКО POST-запросом, никогда не используйте GET-запрос для передачи такой чувствительной информации.
  2. Если такие имя пользователя и пароль существуют, то необходимо создать сессионный токен и привязать его к учётной записи. В простейшем случае токеном может выступать произвольная строка, которую можно сгенерировать с помощью библиотеки securerandom и класса SecureRandom. В промылшенности постепенно набирает популярность формат JWT. Для привязки достаточно в списке пользователей для каждого из них хранить список последних токенов (или только текущий токен).
  3. Данный токен необходимо передать пользователю, чтобы он использовал его при последующих обращениях к серверу. Для решения этой задачи используется механизм Cookie. В простейшем случае Cookie - набор пар ключ-значение, которые передаются между браузером и сервером при каждом запросе. Вы можете добавлять и удалять пары. Размер данного хранилища ограничен и туда не следует помещать больше пары действительно необходимых ключей.

    По умолчанию библиотека Sinatra использует Cookies для хранения сессионных переменных, чем мы и воспользуемся. В сессионные переменные необходимо поместить имя пользователя и его авторизационный токен.

  4. Для всех ресурсов, что требуют авторизации необходимо проверять сессионные переменные, сравнивать их с хранящимися на стороне сервера и делать вывод: является ли пользователь тем, кем хочет представиться или нет. Если он неправ, то набор Cookie надо очищать и перенаправлять пользователя на страницу авторизации (входа).

Для работы с сессионными переменными в Sinatra достаточно обратиться к переменной session. Данная переменная содержит в себе хеш, который помещается в сессионный объект, связанный с текущим соединением к серверу. Для работы с ним доступны все методы класса Hash, без ограничений. Состояние переменной в конце метода определяет содержимое сессии в результате обработки запроса.

Фильтры и методы-помощники

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

Для описания фильтров используются методы before и after:

before '/protected/*' do
  authenticate!
end

after '/create/:slug' do |slug|
  session[:last_slug] = slug
end

Методы-помощники в свою очередь могут быть вызваны явно в том месте, где они необходимы. Для определения помощника вам необходимо создать модуль-примесь и определить в нём необходимые методы. Затем необходимо данную примесь подключить к приложению, вызывав метод helpers.

module FooUtils
  def foo(name) "#{name}foo" end
end

module BarUtils
  def bar(name) "#{name}bar" end
end

helpers FooUtils, BarUtils

Данные методы-помощники можно вызывать как в теле метода-обработчика, так и в шаблонах. В первом случае вы можете разместить в помощнике общую логику по обработке данных, во втором случае - описать особенности представления одинаковых данных.

Задача

Создайте простой, сайт, который будет решать следующие задачи:

  1. Пользователь может зарегистрироваться на сайте, указав псевдоним и пароль. На форме регистрации вы должны проверить:
    • Что пользователя с таким псевдонимом не существует на данном сайте.
    • Что длина пароля больше, чем 7 символов.
    • Что пароль и его повтор совпадают.
  2. Пользователь может пройти авторизацию на сайте, указав псевдоним и пароль. После успешной авторизации пользователю необходимо показать список пользователей.
    • Если пользователь указал несуществующий псевдоним, об этом надо оповестить.
    • Если пользователь указал неверный пароль, об этом надо оповестить.
  3. Авторизованный пользователь может просматривать список зарегистрированных пользователей. Неавторизованный пользователь не должен иметь доступ к данному списку. Список должен быть отсортирован по имени пользователя.
    • Просмотр списка происходит постранично. Т.е. одновременно на странице не должно быть показано более 5 существующих пользователей.
    • Внизу страницы должен располагаться блок перехода между страницами, если на сайте сейчас зарегистрировано более 5 пользователей.
    • Для указания конкретной страницы используйте параметры запроса.
  4. Авторизованный пользователь может выйти из системы. В этом случае доступ ко списку пользователей для него должен быть ограничен.