Рейтинг@Mail.ru
[Войти] [Зарегистрироваться]

Наши друзья и партнеры

UnixForum
Беспроводные выключатели nooLite купить дешевый 
компьютер родом из Dhgate.com

Lines Club

Ищем достойных соперников.

Библиотека сайта или "Мой Linux Documentation Project"

Фреймворк Yesod

Глава 22 из книги "Архитектура приложений с открытым исходным кодом", том 2.

Оригинал: Yesod
Автор: Michael Snoyman
Перевод: Н.Ромоданов

22.5. Yesod

Если мы посмотрим на типичную парадигму «Модель-Представление-Контроллер» («Model-View-Controller» - MVC), то Persistent является моделью, а Shakespeare является преставлением. Тогда все, что остается Yesod, это выступать в роли контроллера.

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

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

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

Маршруты

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

/ HomepageR GET
/add-entry AddEntryR GET POST
/entry/#EntryId EntryR GET

В первой строке определена домашняя страница. Здесь говорится - «Я представляю собой корневой каталог домена, мое имя HomepageR и я отвечаю на запросы GET». Завершающий символ «R» в именах ресурсов является просто общепринятым соглашением, в нем не закладывается никакого общего смысла, кроме как просигнализировать разработчику о том, что нечто является маршрутом.

Во второй строке определена страница добавочной записи. На этот раз мы отвечаем на оба запроса GET и POST. Вы удивитесь, почему в Yesod, в отличие от большинства фреймворков, требуется, чтобы вы явно указывали методы ваших запросов. Причина в том, что Yesod старается придерживаться принципов RESTful настолько, насколько это возможно, а запросы GET и POST по смыслу действительно очень различные. Мало того, что вы устанавливаете эти два метода по отдельности, затем вы отдельно определяете для них функции обработчиков. В действительности, это дополнительная функция в Yesod. Если вы хотите, вы можете убрать из списка названия методов и функции ваших обработчиков будут использоваться для всех методов запроса.

Третья строка немного интереснее. После второго «слеша» у на есть #EntryId. Таким образом определяется параметр EntryId. Мы уже ссылались на эту функцию в разделе о компоненте Persistent: Yesod будет автоматически строить компонент, представляющий собой путь к соответствующему значению ID. Предположим, что на серверной стороне у нас используется SQL (о Mongo поговорим позже), и если пользователь сделает запрос /entry/5, то функции обработчика будет вызвана с аргументом EntryId 5. Но если пользователь сделает запрос /entry/some-blog-post, то Yesod вернет значение 404.

Очевидно, что это также возможно в большинстве других веб фреймворков. Например, в подходе, применяемом в Django, можно использовать регулярные выражения для проверки соответствия маршрутов, например, r"/entry/(\d+)". Однако подход, применяемый в Yesod, имеет ряд преимуществ:

  • Ввод «EntryId» семантически гораздо более удобен/дружественен для разработчика , чем регулярное выражение.
  • С помощью регулярных выражений нельзя выразить все (или по крайней мере, нельзя это сделать лаконично). В Yesod мы можем использовать /calendar/#Day; вы хотите набрать регулярное выражение для того, чтобы сравнивать даты в ваших маршрутах?
  • Yesod также автоматически находит для нас пути. В случае использования календаря, наша функция обработки получит значение Day. В эквиваленте в Django, функция получит кусок текста, по которому нужно будет выполнять поиск самостоятельно. Это утомительно, это требуется каждый раз повторять и это неэффективно.
  • До сих пор мы предполагали, что идентификатор базы данных ID является простой строкой цифр. Но что, если он более сложен? В MongoDB, например, используются идентификаторы GUID. В Yesod ваш запрос #EntryId все равно будет работать, а система типов проинструктирует Yesod, как анализировать маршрут. В системе регулярных выражений, вам придется пройти по всем вашим маршрутам и заменить \d+ на чудовищно сложное регулярное выражение, необходимое для сравнения идентификаторов GUID.

Адреса типобезопасных URL

Такой подход к маршрутизации порождает одну из самых мощных функций Yesod: типобезопасные адреса URL. Вместо того, чтобы объединять вместе части текста со ссылками, обозначающими маршрут, каждый маршрут в вашем приложении может быть представлен с помощью значения языка Haskell. Благодаря этому сразу исчезает большое количество ошибок 404 Not Found (404 Не найдено): просто невозможно получить неправильный URL. (Все еще можно сформировать URL, который приведет к ошибке 404, например, из-за ссылки на несуществующее сообщение в блоге. Тем не менее, все адреса будут сформированы правильно).

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

data MySiteRoute = HomepageR
                 | AddEntryR
                 | EntryR EntryId

Если вы хотите перейти по ссылке на домашнюю странице, вы используете HomepageR. Чтобы разместить ссылку на конкретную запись, вы должны использовать конструктор EntryR с параметром EntryId. Например, чтобы создать новую запись и перейти на нее, вы могли бы написать:

entryId <- insert (Entry "My Entry" "Some content")
redirect RedirectTemporary (EntryR entryId)

Во всех языках Hamlet, Lucius и Julius есть встроенная поддержка таких типобезопасный адресов URL. Внутри шаблона на языке Hamlet вы можете легко создать ссылку на страницу с дополнительной записью:

<a href=@{AddEntryR}>Create a new entry.

Что же самое интересное? Точно также, как и в случае с сущностями Persistent, компилятор обеспечит вам полный порядок. Если вы поменяли какие-либо из ваших маршрутов (например, вы хотите включить в число ваших маршрутов год и месяц), Yesod заставит вас повсюду в коде обновить каждую ссылку.


Далее: Обработчики и виджеты


Эта статья еще не оценивалась
Вы сможете оценить статью и оставить комментарий, если войдете или зарегистрируетесь.
Только зарегистрированные пользователи могут оценивать и комментировать статьи.

Комментарии отсутствуют