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

Хотя сейчас мы читаем входные данные из STDIN, было бы также хорошим улучшением, если бы мы разрешили передачу входного файла для чтения входных данных. Crystal определяет константу ARGF, которая позволяет считывать данные из файла и возвращаться к STDIN, если файлы не предоставлены. ARGF также является вводом-выводом, поэтому мы можем просто заменить STDIN на ARGF в src/transform_cli.cr. Мы можем проверить это изменение, записав выходные данные последнего вызова в файл, скажем, input.yaml. Затем запустите приложение, передав файл в качестве второго аргумента после фильтра. Полная команда будет выглядеть так: crystal src/transform_cli.cr. input.yaml. Однако при запуске вы заметите ошибки: Необработанное исключение: Ошибка чтения файла: Является каталогом (IO::Error). Вы можете задаться вопросом, почему это так, но ответ заключается в том, как работает ARGF.

ARGF сначала проверит, пуст ли ARGV. Если да, то будет выполнено чтение из STDIN. Если ARGV не пуст, предполагается, что каждое значение в ARGV представляет файл для чтения. В нашем случае ARGV не пуст, поскольку содержит [.", "input.yaml"], поэтому он пытается прочитать первый файл, который в данном случае представляет собой точку, обозначающую текущую папку. Поскольку папку нельзя прочитать как файл, возникает исключение, которое мы видели. Чтобы обойти эту проблему, нам нужно убедиться, что ARGV содержит только тот файл, который мы хотим прочитать, прежде чем вызывать ARGF#gets_to_end. Самый простой способ справиться с этой проблемой — вызвать метод #shift для ARGV, который работает, поскольку это массив. Этот метод удаляет первый элемент массива и возвращает его, в результате чего в ARGV остается только файл.

Однако есть еще одна проблема, которую нам также необходимо решить. Поскольку мы используем ARGV напрямую для предоставления входных аргументов jq, нам нужно будет провести некоторый рефакторинг, чтобы иметь возможность получить доступ к фильтру перед вызовом #gets_to_end. Мы можем добиться этого, переместив часть логики из src/transform_cli.cr в src/processor.cr! Обновите src/processor.cr, чтобы он выглядел так:

class Transform::Processor

  def process : Nil

    filter = ARGV.shift

    input = ARGF.gets_to_end

    output_data = String.build do |str|

      Process.run(

        "jq",

        [filter],

        input: IO::Memory.new(

        Transform::YAML.deserialize input

        ),

        output: str

      )

    end

      STDOUT.puts Transform::YAML.serialize output_data

  end

end

Ключевым дополнением здесь является введение filter = ARGV.shift, который гарантирует, что остальная часть ARGV будет содержать только тот файл, который мы хотим использовать в качестве входных данных. Затем мы используем нашу переменную как единственный элемент в массиве, представляющий аргументы, которые мы передаем в jq, заменяя жестко закодированную ссылку ARGV.

Также обратите внимание, что мы удалили входной аргумент из метода #process. Причина этого в том, что все входные данные теперь получаются изнутри самого метода, и поэтому нет смысла принимать внешние входные данные. Еще одним примечательным изменением было изменение типа возвращаемого значения метода на Nil, поскольку мы выводим его непосредственно в STDOUT. Это немного снижает гибкость метода, но об этом также будет сказано в следующем разделе.

Есть еще одна вещь, которую нам нужно обработать, прежде чем мы сможем объявить рефакторинг завершенным: что произойдет, если в jq будет передан недопустимый фильтр (или данные)? В настоящее время это вызовет не очень дружелюбное исключение. Что нам действительно нужно сделать, так это проверить, успешно ли выполнен jq, и если нет, записать сообщение об ошибке в STDERR и выйти из приложения, внеся следующие изменения в src/processor.cr:

class Transform::Processor

  def process : Nil

    filter = ARGV.shift

    input = ARGF.gets_to_end

    output_data = String.build do |str|

      run = Process.run(

        "jq",

        [filter],

        input: IO::Memory.new(

          Transform::YAML.deserialize input

        ),

        output: str,

        error: STDERR

      )

    exit 1 unless run.success?

    end

    STDOUT.puts Transform::YAML.serialize output_data

  end

end

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

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

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

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

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

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

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

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

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