Crystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI - Джордж Дитрих
Книгу Crystal Programming. Введение на основе проекта в создание эффективных, безопасных и читаемых веб-приложений и приложений CLI - Джордж Дитрих читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
Откройте src/yaml.cr и обновите первый аргумент, чтобы он принимал IO, а также добавьте еще один аргумент IO, который будет представлять выходные данные. Оба метода .parse поддерживают String | IO входы, поэтому нам там ничего особенного делать не нужно. Методы #to_* также имеют перегрузку на основе IO, которой мы передадим новый выходной аргумент. Наконец, поскольку этот метод больше не будет возвращать преобразованные данные в виде строки, мы можем обновить тип возвращаемого значения на Nil. В конечном итоге это должно выглядеть следующим образом:
require "yaml"
require "json"
module Transform::YAML
def self.deserialize(input : IO, output : IO) : Nil
::YAML.parse(input).to_json output
end
def self.serialize(input : IO, output : IO) : Nil
JSON.parse(input).to_yaml output
end
end
Поскольку мы добавили второй аргумент, нам, конечно, также потребуется обновить процессор для передачи второго аргумента. Аналогичным образом, поскольку сейчас мы работаем исключительно с операциями IO, нам нужно будет реализовать новый способ хранения/перемещения данных. Мы можем решить обе эти задачи, используя объекты IO::Memory для хранения преобразованных данных. Кроме того, поскольку они сами относятся к типу IO, мы можем передавать их непосредственно в качестве входных данных в jq.
Конечный результат этого рефакторинга следующий:
class Transform::Processor
def process(input_args : Array(String), input : IO,
output : IO, error : IO) : Nil
filter = input_args.shift
input_buffer = IO::Memory.new
output_buffer = IO::Memory.new
Transform::YAML.deserialize input, input_buffer
input_buffer.rewind
run = Process.run(
"jq",
[filter],
input: input_buffer,
output: output_buffer,
error: error
)
exit 1 unless run.success?
output_buffer.rewind
Transform::YAML.serialize output_buffer, output
end
end
Мы все еще смещаем фильтр с входных аргументов. Однако вместо использования #gets_to_end для получения всех данных из IO мы теперь создаем два экземпляра IO::Memory — первый для хранения данных JSON из преобразования десериализации, а второй для хранения выходных данных JSON через jq.
По сути, это работает так: процесс десериализации будет использовать все данные входного типа IO, выводя преобразованные данные в первый IO::Memory. Затем мы передаем его в качестве входных данных в jq, который записывает обработанные данные во второй IO::Memory. Затем второй экземпляр передается в качестве входного типа IO в метод serialize, который выводит данные непосредственно в выходной тип IO.
Еще один ключевой момент, на который стоит обратить внимание, — это то, как нам нужно вызывать .rewind для буферов до/после запуска логики преобразования. Причина этого связана с тем, как работает IO::Memory. По мере записи в него данных он продолжает добавлять данные в конец.
Другой способ подумать об этом — представить, что вы пишете эссе. Чем длиннее и длиннее эссе, тем дальше и дальше вы отходите от начала. Вызов .rewind имеет тот же эффект, как если бы вы переместили курсор обратно в начало эссе. Или, в случае с нашим буфером, он сбрасывает буфер, чтобы будущие чтения начинались с самого начала. Если бы мы этого не сделали, jq — и наша логика преобразования — начали бы читать с конца буфера, что привело бы к некорректному выводу, поскольку он по существу пуст.
Следуя нашей идее разрешить использование нашего приложения в чужом проекте, нам нужно улучшить еще одну вещь. В настоящее время мы выходим из процесса, если вызов jq завершается неудачей. Было бы нехорошо, если бы кто-то использовал это, например, в веб-фреймворке, а мы случайно отключили его сервер! К счастью, исправить это просто. Вместо вызова exit 1 нам следует просто вызвать исключение, которое мы можем проверить в точке входа, специфичной для CLI. Или, другими словами, замените эту строку на raise RuntimeError.new, если только run.success?. Затем обновите src/transform_cli.cr следующим образом:
require "./transform"
begin
Transform::Processor.new.process ARGV, STDIN, STDOUT, STDERR rescue ex : RuntimeError
exit 1
end
Сделав это таким образом, мы по-прежнему будем иметь правильный код завершения при использовании в качестве CLI, но также сможем лучше использовать наше приложение в контексте библиотеки, поскольку исключение можно будет спасти и корректно обработать. Но подождите — мы много говорили об использовании нашего приложения в качестве библиотеки в другом проекте, но как это выглядит?
Во-первых, пользователям нашей библиотеки необходимо будет установить наш проект как сегмент — подробнее об этом в Главе 8 «Использование внешних библиотек». Тогда они могли бы потребовать, чтобы наш src/transform.cr имел доступ к нашему процессору и логике преобразования. Это было бы намного сложнее, если бы мы не использовали отдельную точку входа для контекста CLI. Отсюда они могли создать тип Processor и использовать его в соответствии со своими потребностями. Например, предположим, что они хотят обработать тело ответа HTTP-запроса, выведя преобразованные данные в файл. Это будет выглядеть примерно так:
require "http/client"
require "transform"
private FILTER = %({"name": .info.title, "swagger_version": .swagger, "endpoints": .paths | keys})
HTTP::Client.get "https://petstore.swagger.io/v2/swagger.yaml" do
|response|
File.open("./out.yml", "wb") do |file|
Transform::Processor.new.process [FILTER], response.body_io, file
end
end
В результате файл будет следующим:
---
name: Swagger Petstore swagger_version: "2.0" endpoints:
- /pet
- /pet/findByStatus
- /pet/findByTags
- /pet/{petId}
- /pet/{petId}/uploadImage
- /store/inventory
- /store/order
- /store/order/{orderId}
- /user
- /user/createWithArray
- /user/createWithList
- /user/login
- /user/logout
- /user/{username}
Эта способность может быть очень ценной для кого-то другого, поскольку может означать, что им не придется реализовывать эту логику самостоятельно.
Теперь, когда и наш процессор, и типы преобразования используют IO, мы можем сделать еще одну оптимизацию. Текущая логика преобразования использует метод класса .parse в соответствующем модуле формата. Этот метод очень удобен, но имеет один главный недостаток: он загружает все входные данные
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Kelly11 июль 05:50 Хорошо написанная книга, каждая глава читалась взахлёб. Всё описано так ярко: образы, чувства, страх, неизбежность, словно я сама... Не говори никому. Реальная история сестер, выросших с матерью-убийцей - Грегг Олсен
-
Аноним09 июль 05:35 Главная героиня- Странная баба, со всеми переспала. Сосед. Татьяна Шумакова.... Сосед - Татьяна Александровна Шумкова
-
ANDREY07 июль 21:04 Прекрасное произведение с первой книги!... Роботам вход воспрещен. Том 7 - Дмитрий Дорничев