С этого момента мы начнем использовать файл
Давайте начнем с создания файла
class Transform::Processor
def process(input : String) : String
output_data = String.build do |str|
Process.run(
"jq",
[%([.[] | {"id": (.id + 1), "name": .author.name}])],
input: IO::Memory.new(
Transform::YAML.deserialize input
),
output: str
)
end
Transform::YAML.serialize output_data
end
end
Наличие этого класса делает наш код намного более гибким и пригодным для повторного использования. Мы можем создать объект Transform::Processor
и вызывать его метод #process
несколько раз с различными входными строками. Далее, давайте используем этот новый тип в
require "./transform"
INPUT_DATA = <←YAML
---
- id: 1
author:
name: Jim
- id: 2
author:
name: Bob
YAML
puts Transform::Processor.new.process INPUT_DATA
Наконец,
require "./processor"
require "./yaml"
module Transform
VERSION = "0.1.0"
end
Запуск
Аргументы, передаваемые программе CLI, отображаются через константу ARGV в виде Array(String)
. Сам код, позволяющий использовать это, довольно прост, учитывая, что аргументы jq уже принимают массив строк, который у нас на данный момент жестко запрограммирован. Мы можем просто заменить этот массив константой ARGV, и все будет в порядке.
class Transform::Processor
def process(input : String) : String
output_data = String.build do |str|
Process.run("jq",
ARGV,
input: IO::Memory.new(Transform::YAML.deserialize
input
),
output: str
)
end
Transform::YAML.serialize output_data
end
end
Кроме того, поскольку фильтр больше не является жестко запрограммированным, нам нужно будет ввести его вручную. Запуск crystal src/transform_cli.cr '[.[] | {"id": (.id + 1), "name": .author.name}]'
снова выдает тот же результат, но гораздо более гибким способом.
Если вы предпочитаете использовать crystal run, команду нужно будет немного изменить, чтобы учесть различную семантику каждого варианта. В этом случае команда была бы crystal run src/transform_cli.cr -- '[.[] | {"id": (.id + 1), "name": .author.name }]'
, где параметр --
сообщает команде запуска, что должны быть переданы будущие аргументы к исполняемому файлу, а не в качестве аргументов для самой команды запуска.
Стандартная библиотека Crystal также включает тип OptionParser
, который предоставляет DSL, позволяющий описывать аргументы, которые принимает CLI, обрабатывать их синтаксический анализ из
Резюме
На данный момент наш интерфейс командной строки отвечает всем нашим требованиям. Мы можем преобразовать несколько жестко запрограммированных входных данных YAML в JSON и обработать их с помощью фильтра jq, а выходные данные преобразовать обратно в YAML и вывести для нашего просмотра, все время принимая фильтр jq в качестве аргумента CLI. Однако нашей реализации по-прежнему не хватает гибкости и производительности. В следующей главе будет рассказано, как использовать типы ввода-вывода (IO) для улучшения приложения в соответствии с обоими этими критериями.