litbaza книги онлайнРазная литератураCrystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI - Джордж Дитрих

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 44 45 46 47 48 49 50 51 52 ... 75
Перейти на страницу:
различной информации, которую можно частично использовать для обработки ответа. В нашем случае нам нужны только параметры view и request, последний из которых используется для получения всех конфигураций аннотаций, определенных на соответствующем маршруте. Здесь в игру вступает аннотация, которую мы создали ранее, поскольку мы можем проверить, применяется ли ее экземпляр к действию контроллера, связанному с текущим запросом. См. https://athenaframework.org/Framework/View/ для получения дополнительной информации о том, что отображается через эти параметры.

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

Наконец, мы используем Crinja для получения шаблона на основе имени в аннотации и его визуализации, используя значение, возвращаемое из действия контроллера, в качестве значения объекта данных. Затем мы используем визуализированное содержимое в качестве тела ответа для ATH::Response, устанавливая тип содержимого ответа на text/html.

Чтобы включить такое поведение, нам просто нужно применить аннотацию @ [Blog::Annotations::Template("article.html.j2")] к нашему методу #article в ArticleController. Мы можем все проверить, сделав еще один запрос:

curl --request GET 'http://localhost:3000/article/1' --header

'accept: text/html'

Ответом в этом контексте должен быть наш HTML-шаблон. Если вы установите заголовок application/json или вообще удалите его, ответом должен быть JSON.

Резюме

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

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

Дальнейшее чтение

• https://athenaframework.org/EventDispatcher/

• https://athenaframework.org/Console/

• https://athenaframework.org/Routing/

Часть 4: Метапрограммирование

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

Эта часть содержит следующие главы:

• Глава 10, Работа с макросами

• Глава 11, Введение в аннотации

• Глава 12, Использование анализа типов во время компиляции

• Глава 13, Расширенное использование макросов

10. Работа с макросами

В этой главе мы собираемся исследовать мир метапрограммирования. Метапрограммирование может быть отличным способом «СУШИТЬ» (DRY) ваш код путем объединения шаблонного кода в фрагменты многократного использования или путем обработки данных во время компиляции для создания дополнительного кода. Сначала мы рассмотрим основную часть этой функции: макросы.

В этой главе мы рассмотрим следующие темы:

• Определение макросов

• Понимание API макросов.

• Изучение макросов.

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

Технические требования

Для этой главы вам понадобится работающая установка Crystal.

Инструкции по настройке Crystal можно найти в Главе 1 «Введение в Crystal».

Все примеры кода в этой главе можно найти в папке Chapter 10 репозитория GitHub этой книги: https://github.com/PacktPublishing/Crystal-Programming/tree/main/Chapter10.

Определение макросов

В Crystal макрос имеет два значения. Как правило, это относится к любому коду, который запускается или расширяется во время компиляции. Однако, более конкретно, это может относиться к типу метода, который принимает узлы AST во время компиляции, тело которых вставляется в программу в момент использования макроса. Примером последнего является макрос property, который вы видели в предыдущих главах, который представляет собой простой способ определения как метода получения, так и метода установки для данной переменной экземпляра:

class Example

  property age : Int32

  def initialize(@age : Int32); end

end

Предыдущий код эквивалентен следующему:

class Example

  @age : Int32

  def initialize(@age : Int32); end

  def age : Int32

    @age

  end

  def age=(@age : Int32)

  end

end

Как мы упоминали ранее, макросы принимают узлы AST во время компиляции и выводят код Crystal, который добавляется в программу, как если бы он был введен вручную. По этой причине property age: Int32 не является частью конечной программы, а только тем, во что оно расширяется — объявлением переменной экземпляра, методом получения и методом установки. Аналогичным образом, поскольку макросы работают на узлах AST во время компиляции, аргументы/значения, используемые внутри макроса, также должны быть доступны во время компиляции. Сюда входит следующее:

• Переменные среды.

• Константы

• Жестко запрограммированные значения.

• Жестко закодированные значения, созданные с помощью другого макроса.

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

macro print_value(value)

  {{pp value}}

  pp {{value}}

end

name = "George"

print_value name

Запуск этой программы приведет к следующему выводу:

name

"George"

Главное, на что следует обратить внимание, — это вывод значения, когда оно находится в контексте макроса. Поскольку макросы принимают узлы AST, макрос не имеет доступа к текущему значению переменной времени выполнения, такой как имя. Вместо этого типом значения в контексте макроса является Var, который представляет локальную переменную или аргумент блока. Это можно подтвердить, добавив в макрос строку, состоящую из {{pp value.class_name}}, которая в конечном итоге напечатает "Var”. Мы узнаем больше об узлах AST позже в этой главе.

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

1 ... 44 45 46 47 48 49 50 51 52 ... 75
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?