Читаем Crystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI полностью

Здесь мы определяем изменяемую константу, которая будет содержать зарегистрированные типы, сами типы и макрос, который будет их регистрировать. Мы также вызываем #resolve для типа, переданного макросу, поскольку типом аргумента макроса будет Path. Метод #resolve преобразует путь в TypeNode, который представляет собой типы переменных экземпляра. Метод #resolve необходимо использовать только в том случае, если тип передается по имени, например, в качестве аргумента макроса, тогда как макропеременная @type всегда будет TypeNode.

Теперь, когда у нас определена сторона регистрации, мы можем перейти к стороне времени выполнения. Эта часть представляет собой просто метод, который генерирует оператор case, используя значения, определенные в константах MODELS, например:

def model_by_name(name)

  {% begin %}

    case name

    {% for model in MODELS %}

      when {{model.name.stringify}} then {{model}}

    {% end %}

    else

      raise "model unknown"

    end

  {% end %}

end

Отсюда мы можем пойти дальше и добавить следующий код:

pp {{ MODELS }}

pp model_by_name "Cat"

register_model Cat

register_model Dog

pp {{ MODELS }}

pp model_by_name "Cat"

После его запуска вы увидите следующее, напечатанное на вашем терминале:

[]

Cat

[Cat, Dog]

Cat

Мы видим, что первый массив пуст, поскольку ни один тип не был зарегистрирован, хотя строка “Cat" может быть успешно разрешена, даже если после нее зарегистрирован связанный тип. Причина этого в том, что регистрация происходит во время компиляции, а разрешение — во время выполнения. Другими словами, регистрация модели происходит до того, как программа начнет выполняться, независимо от того, в каком месте исходного кода зарегистрированы типы.

После регистрации двух типов мы видим, что массив MODELS содержит их. Наконец, это еще раз показывает, что его можно было разрешить при вызове до или после регистрации связанного типа. Как упоминалось ранее в этой главе, макросы не имеют такой же типизации, как обычный код Crystal. Из-за этого к макросам невозможно добавлять ограничения типов. Это означает, что пользователь может передать в макрос .register_model все, что пожелает, что может привести к не столь очевидным ошибкам. Например, если они случайно передали "Time" вместо Time, это приведет к следующей ошибке: неопределенный метод макроса 'StringLiteral#resolve'. В следующем разделе мы собираемся изучить способ сделать источник ошибки более очевидным.

<p>Создание пользовательских ошибок времени компиляции</p>

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

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

В последних нескольких главах мы использовали различные макрометоды верхнего уровня, такие как #env, #flag и #debug. Другой метод верхнего уровня — #raise, который вызывает ошибку во время компиляции и позволяет предоставить собственное сообщение. Мы можем использовать это с некоторой условной логикой, чтобы определить, не является ли значение, переданное нашему макросу, Path. Наш обновленный макрос будет выглядеть так:

macro exclude_type(type)

  {% raise %(Expected argument to 'exclude_type' to be

    'Path', got '#{type.class_name.id}'.) unless type.is_a?

      Path %}

  {% EXCLUDED_TYPES << type.resolve %}

end

Теперь, если бы мы вызвали макрос с "Time", мы бы получили ошибку:

In mutable_constants.cr:43:1

43 | exclude_type "Time"

     ^-----------

Error: Expected argument to 'exclude_type' to be 'Path', got 'StringLiteral'.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных