Из-за недавних событий, которые произошли в моей жизни во время программирования, я застрял в петле, где я пишу гораздо меньше кода, чем хотел. Наконец-то я преодолел множество проблем и сел думать, как сделать мой исходный код CLI намного лучше. Я получил несколько идей о времени загрузки и написании более чистого кода. Мой исходный код под названием «cli.rb» выглядел примерно так:

Как вы уже можете заметить, он кажется очень загроможденным, более 97 строк кода только для нескольких функций и не так много собак. Он становится немного меньше, но больше соответствует шаблону со следующим набором кода, который мне пришлось реорганизовать. Но чтобы прояснить, что происходит в моем коде, я начал с метода call, который дает пользователю другой метод, включающий строку «Список собак»; в нем также перечислены все собаки с номерами 1–4, чтобы пользователь мог ввести номер, чтобы выбрать собаку.

Теперь самое интересное — метод меню, который я включил в метод вызова. Именно здесь происходит волшебство между пользователем и интерфейсом командной строки. Я начинаю с input = to nil, используя цикл while, установленный на «input != «exit»». Я зацикливаю строку, которая просит пользователя ввести число 1–4, чтобы загрузить для него биографию собаки. , если они не могут вспомнить список, они могут ввести «список», чтобы снова увидеть список, и, наконец, «выйти», если они хотят остановить программу. Используя ввод с треском и установив его на строку «выход», я даю пользователю возможность завершить программу, когда они захотят. Мне также пришлось включить «input = gets.chomp.downcase», чтобы у пользователя не было проблем с ошибками с использованием заглавных букв в любом месте, т.е. «Мопс» не работал бы, если бы я не включал нижний регистр, это выдавало бы пользователю ошибку . Поэтому вместо этого у меня программа автоматически прописывает все входные строки в нижнем регистре, чтобы не было ошибок.

Углубившись в метод меню, вы увидите, что оператор if имеет значение 'input.to_i › 0', а для «doggo» задана переменная класса «@dogs[input.to_i-1]» и что он помещен out «#{doggo.breed}». Это делает то, что он считывает данные с веб-сайта, на который мы обратимся позже, а затем печатает для пользователя строку с необходимой ему информацией. Причина, по которой у меня есть input.to_i-1, заключается в том, что программы начинаются с 0, а мы, люди, начинаем с 1; чтобы помочь программе понять, чего хочет пользователь и что программа может понять, у меня есть пользователь, набирающий 1, который программа будет понимать как 0. При этом пользователь получит нужную ему информацию без необходимости идти на компромисс с программой и набирать «0» для чего-либо, указанного как «1». Вы также заметите, что я также вставил операторы elsif для каждого ввода, который пользователь решает ввести в породе, которую он хотел бы выбрать. Если бы они ввели любую другую строку, у меня есть оператор else, чтобы они могли проверить правописание перед вводом или, если они забыли варианты, они могли бы снова набрать «список».

Созданный мной файл парсера был сделан немного лучше, но иногда для его загрузки требовалось некоторое время. Это «dog_scraper.rb»:

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

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

Глядя на то, что я записал, это казалось немного запутанным, тонна сопоставления с образцом и слишком много кода одновременно. Итак, один из первых вопросов, которые я задал, был: «Что может сделать это лучше?» Итак, после нескольких минут гугления, пары часов проб и ошибок я, наконец, обратился за помощью через форум и к более опытному программисту. Вот как выглядит конечный продукт для каждого файла с краткими пояснениями того, что он делает.

Первое, что нужно было сделать, это создать класс для биографии моей собаки. При этом я должен был убедиться, что у него есть пустой массив, а также инициализировать URL-адрес и породу. Это один из краеугольных камней программы, работающей без сбоев. Это создаст новых собак на лету, которые будут объяснены позже, и значительно облегчит понимание. У меня также было имя класса DogBio, разделенное модулем Dog. Теперь о том, что находится в модуле «Собака»…

Это то, что позволяет файлам читать и взаимодействовать друг с другом. Это означает, что я могу вызывать другие методы из других классов для использования в других файлах или классах, наряду с возможностью без проблем использовать pry, nokogiri, open-uri в любом файле. Ниже приведен класс Dogbio.

Создавая класс DogScraper, я сначала должен был убедиться, что его имя отделено от модуля Dog. Затем я записал аксессуар, который принимает породу и биографию. Как объяснялось выше, модуль dog поможет нам использовать различные методы из других классов и файлов.

Теперь вот идет мясная часть класса. Извлекаю данные с веб-сайта Purina, затем перебираю всех собак, которых могу, и убеждаюсь, что использую свой класс DogBio для создания новых собак. Звучит немного странно, так что давайте углубимся. Сначала мне, конечно, пришлось зайти на веб-сайт Purina, а затем посмотреть их список пород собак. Список собак Purina был https://www.puroina.com/dogs/dog- породы. Итак, теперь в моем коде мне пришлось добавить метод класса и иметь пространство имен Nokogiri с HTML и открыть этот веб-сайт в моем коде.

Теперь, когда это сделано, мы должны пойти еще глубже, чтобы найти нужную нам информацию. Я использовал Google Chrome, когда был на веб-сайте Purina, поэтому, чтобы получить правильную информацию, необходимую для моего CLI, мне пришлось использовать кнопку проверки. Чтобы использовать этот инструмент, вы должны щелкнуть правой кнопкой мыши в любом месте страницы и нажать «Проверить». Как только это будет сделано, вы получите что-то вроде этого.

Похоже, там много кода. В нем будет очень сложно найти то, что вам нужно. К счастью, в Chrome есть небольшой инструмент, который помогает находить конкретные вещи, которые вы ищете, наведя курсор на что-то и выделяя свойство на странице. Он расположен ближе к разделу элементов вверху посередине, а изображение представляет собой мышь, наведенную на квадрат. Я использовал это, чтобы помочь найти правильную область, где он перечисляет собак, который оказался div class = блокирует выноску div. Итак, теперь я должен добавить его в свой код, выполнив поиск с использованием предыдущего кода, но теперь назначив doc.

Еще не сделано. Теперь нам нужно перебрать каждую собаку и убедиться, что у них есть имя и биография, но не только это, нам также нужно, чтобы они были созданы в нашем коде, чтобы их можно было вызвать. Итак, на этом мы заканчиваем остальную часть рефакторинга. Вместо того, чтобы жестко кодировать определенных собак, а затем очищать их данные, теперь у нас есть первая очищенная страница, которая состоит из 12 собак, каждая из которых повторяется и помещается в текст для пользователя. Я присвоил переменной имя собаки и использовал строку doc.search. Затем я использовал итератор каждый, чтобы перечислить их все. Я записал 2 переменные и присвоил им разные свойства. Breed использовал dog.search(“span.callout-label”).text, чтобы получить html-тег, а затем поместить его в строку с помощью текста. Затем я присвоил переменной имя url и установил для нее значение dog.search(a.link).attr("href").value, которое захватило ссылку на каждую собаку в итерации. После того, как они были установлены, мне пришлось создать новые объекты собаки. Поэтому я взял из своей старой модели и использовал модуль Dog с интервалом DogBio и создал новый объект собаки, используя новые переменные, которые я только что создал.

Теперь есть небольшая проблема. Ссылка не открывает Purina.com/dogs/dog-breds. Он захватывает только последний бит адреса, не только это, он не захватывает биографию этой собаки и не переводит ее в текстовую форму для пользователя, чтобы исправить это, мне пришлось сделать другой метод. На этот раз я назвал его self.scrape_dog с аргументом dog_bio, который состоит из того, что пользователь выбирает в меню, которое я сделал в файле cli, к нему прикреплен экземпляр породы и URL-адрес этой породы. Я назначаю начало веб-сайта «https://www.purina.com» и добавляю аргумент «собака_био» и беру его URL-адрес на английском языке, теперь программа будет читать ввод пользователя, а затем берет строку «https://». www.purina.com» и прикрепите к нему любой URL-адрес собаки, выбранный пользователем, чтобы у него был полный адрес.

Нам нужно не только написать начало веб-адреса, но нам также нужно получить всю биографию с веб-сайта собаки и также присвоить ей значение. Если вы помните, у нас было средство доступа к bio как в классе dog_scraper, так и в классе dog_bio, это помогает нам читать и писать код и сохранять его на потом. Итак, настало время присвоить другое значение, dog_bio.bio с doc.search("section.mainContent p").text, это то, что содержит абзацы биографии собаки.

Последнее, чего не хватает, нам понадобится позже. У меня должен быть другой метод класса, содержащий код другого метода, чтобы упростить его и перенести в другой файл класса. Поэтому я добавил self.list и поместил в него метод scrape_dogs. Это будет важно на потом. Итак, окончательный вид класса dog_scraper выглядит так.

Это выглядит намного лучше, чем раньше, с менее сложным кодированием и сопоставлением с образцом. Это просто и доступно для чтения гораздо большему количеству людей. Сокращение примерно с 47 строк кода до 24.

Теперь о классе CLI. Мы начнем с того, что снова воспользуемся модулем собаки и назовем его пробелом с именем CLI. Нам не нужно добавлять какие-либо атрибуты для этого класса, поскольку мы полностью берем из других файлов и просто создаем меню и список. Итак, мы начнем с метода экземпляра и назовем его call. Внутри метода call мы поместим все наши методы, такие как меню и список собак. Но сначала мы добавим метод класса scrape_dogs. Затем нам нужно создать метод, который будет отображать список собак, чтобы пользователь мог их прочитать. Мы создаем метод list_dogs, теперь нам нужно перебрать массив собак, которые мы очистили, где, к счастью, у нас уже есть это; он находится в файле Dog_bio, из-за этого нам теперь нужно вызвать файл и заставить его отображать всех собак, используя Dog::DogBio.all, затем я устанавливаю его в переменную класса собак. Убедившись, что это работает, я использовал pry, и если все сделано правильно с приведенным выше кодом, в терминале это должно выглядеть примерно так.

Теперь мы должны выполнить итерацию по всем собакам и заставить их отображать свою породу после вызова, а также установить для них число, чтобы, когда пользователь выбирает это число, порода отображалась. Итак, мы записываем нашу переменную класса и, используя каждую с индексом 1, мы можем взять каждую собаку и установить для нее число, затем у нас есть итерация, распечатывающая строку с целым числом, которое прикреплено к каждой отдельной собаке и породе собак с помощью разрыв строки, чтобы пользователь не запутался при чтении всех строк без разрывов строк и не запутался при чтении. Наш метод списка собак теперь готов и должен выглядеть примерно так!

Следующим будет наше меню для пользователя, нам нужно что-то простое и доступное практически для всех, чтобы его можно было использовать. Итак, я сначала начинаю вызывать меню метода экземпляра, у меня для ввода установлено значение nil, и я использую цикл while до того места, где он заканчивается, когда я прошу кого-то ввести выход, если они этого не сделают, они получат сообщение с вопросом, каких собак они будут нравится видеть. Теперь мы должны дать возможность пользователю, мы создаем переменную по имени input в нашем цикле и устанавливаем ее в get.chomp.downcase, чтобы пользователь имел возможность вводить что-то. Не только это, но и если они Напишите с большой буквы «Е» в «Выходе», чтобы они не застряли в петле и не знали, почему. Chomp используется, чтобы избавиться от завершающего символа новой строки, который программа прикрепляет к каждому концу строки. Я также обернул переменную класса собак, которая содержит всех собак, и установил для нее длину, чтобы она подсчитывала, сколько собак находится в массиве, и поэтому мне не нужно постоянно обновлять, когда я решу добавить больше собак в программу. . Пока это будет выглядеть так.

Сложная часть меню — выбрать конкретную собаку, о которой пользователь хочет узнать больше. Для этого мы теперь должны использовать оператор if и установить для него определенные условия, чтобы мы могли подобрать нужных собак для пользователя. Я вставил в оператор if переменную input.to_i › 0, что означает, что когда пользователь вводит число вместо того, чтобы оно выводилось в виде строки, оно будет зарегистрировано как целое число, и если для него установлено значение 0, пользователь запустит программу, если они введут целое число выше 0. Мне также пришлось написать условие, которое пользователь должен был ввести в целое число, меньшее или равное методу класса Dogs.length, это произойдет hand позже, когда я использую оператор else. Прямо сейчас код выглядит довольно хорошо.

Теперь нам нужно закончить оператор if, добавить несколько elsif и, наконец, указать else в самом конце. Завершая работу с оператором if, я решил создать переменную в рамках метода, называемую doggo, которая принимает метод класса собак, присоединенный к вводу от пользователя, установленному на целое число, но вычитаемому на 1, потому что компьютеры начинают свой счет. в 0 при подсчете из массива или большинства вещей, в то время как люди начинают считать с 1. Затем я распечатываю строку с путями, которая вызывает переменную, берет метод класса и выводит породу только с использованием .breed вместе с разрывом строки в в конце будет напечатано имя собаки. Затем мне нужна биография собаки, поэтому я снова обращаюсь к классу DogScraper.scrape_dog, снова передавая ему аргумент doggo и устанавливая, если doggo.bio, затем распечатывая саму биографию собаки с разрывом строки. Если часть не помогает с очисткой, как только пользователь попытается выбрать ту же собаку еще раз, программа не будет постоянно очищать, а опубликует ту же собаку, которую он запросил, прежде чем сделать все более эффективным.

Для последних частей меню я использовал операторы elsif в операторе if, чтобы дать пользователю возможность вызывать список с помощью метода, который мы создали ранее с помощью «list_dogs». Я также создал еще один метод под названием «до свидания» и заставил его распечатать прощальное сообщение для пользователя, ничего особенного, это просто строка, я настроил ее на выход, так что когда пользователь хочет завершить программу, он получает крошечное сообщение. Наконец, причина, по которой я добавил «&& input.to_i ≤= @dogs.length», заключалась в операторе else, который выводит «ввод недействителен…» и дает аналогичные параметры из списка, чтобы помочь пользователю, вместо того, чтобы программа не знала, что идет и рушится.

Наконец-то мы закончили наш класс CLI!

Спасибо, что нашли время, чтобы прочитать весь рефакторинг кода и посмотреть, как я делаю свои классы Dog Bio! Я действительно оценил это!