Целью данного занятия является закрепление полученных знаний о создании классов на языке Ruby, а также использования стандартных примесей для решения повседневных задач обработки наборов данных.

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

  • Общее описание назначение формата YAML на Википедии.
  • Официальная страница формата данных YAML.
  • Официальный стандарт 1.2 формата данных с большим количеством примеров YAML 1.2.

Формат позволяет описать произвольно сложную структуру из списков и хешей. Потом её можно легко преобразовать в соответствующие структуры языка Ruby.

Начальное состояние состояние YAML-документа, содержащего данные для задания, приведено ниже:

students:
  - id: 0
    name: Ivan
    surname: Loskutov
  - id: 2
    name: Maria
    surname: Dovlatova
  - id: 5
    name: Alice
    surname: Dilbert
courses:
  - name: Biology
    grades:
      - student_id: 0
        grade: 5.3
      - student_id: 2
        grade: 4.5
      - student_id: 5
        grade: 5.0
  - name: Math
    grades:
      - student_id: 5
        grade: 4.6
      - student_id: 0
        grade: 5.1
      - student_id: 2
        grade: 5.2
  - name: Computer Science
  - name:

Приложение должно считывать информацию из YAML-документа и позволять пользователю:

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

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

Дополнительно. Рекомендуется также реализовать следующие функции:

  • Добавление нового студента в список студентов.
  • Редактирование информации о студенте из списка.
  • Добавление нового предмета в список предметов.
  • Редактирование названия предмета в списке.
  • Удаление предмета из списка предметов.
  • Удаление студента из списка. Внимание При удалении студента необходимо также удалять и всего его оценки, выставленные по предметам.

Технические требования к реализации

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

Работа с YAML-документами

В отличие от библиотеки csv библиотека yaml ориентирована на работу со строками, а не с файлами. Это сделано сделано в перую очередь вииду того, что YAML-документы могут быть не только считаны из файла, но также получены другими путями, например через сетевое взаимодействие. Для разрабатываемого приложения это означает, что вам сначала необходимо будет считать содержимое файла в строку, а затем воспользоваться методами библиотеки yaml.

Для считывания всех данных из файла необходимо воспользоваться методом #read класса File. То есть необходимо сначала создать объект класса файл, передав конструктору в качестве аргумента путь к файлу, а затем прочитать всё содержимое файла с помощью данного метода. Желательно перед открытием и считыванием информации из файла проверить, что такой файл существует с помощью метода #exist?. После окончания считывания информации из файла не забудьте закрыть данный файл, используя метод #close.

После успешного считывания данных из файла необходимо преобразовать строку в Ruby-объекты. Для этого используется метод .load. Методу в качестве аргумента передаётся строка, а он возвращает созданные Ruby-объекты. Для обратного преобразования использутся метод .dump модуля YAML или метод .to_yaml, который определяется у базового объекта Object.

Если вы хотите более глубоко разобраться с возможностями библиотеки по работе с YAML-документами, тогда вам необходимо обратиться к официальной документации джема psych.

Предлагаемый подход к решению задачи

  1. Создайте каталог, в котором далее будете разрабатывать приложение.
  2. Создайте подкаталоги bin и lib в созданном каталоге.
  3. Установите джем bundler и инициализируйте с помощью Bundler его конфигурационный файл.
  4. Добавьте в качестве зависимости и установие джем rubocop. После выполнения каждого шага необходимо запускать rubocop и исправлять код в соответствии с его замечаниями. После их исправления переходите к следующему шагу.
  5. Создайте конфигурационный файл для Rubocop и поместите его в корень проекта.
  6. В каталоге lib создайте файл core.rb.
    • В данном файле создайте класс Core и определите в нём метод #run.
    • Данный метод должен печатать приветствие на стандартный поток вывода. Приветствие нужно только лишь для того, чтобы вы смогли убедиться, что метод работает.
  7. В каталоге bin создайте файл application.rb.
    • В данном файле подключите файл core, создайте экземпляр класса Core и вызовите его метод #run.
    • Больше никакого кода в данный файл добавлять не надо, а всю разработку надо вести в каталоге lib.
  8. В корне проекта созадйте каталог data и создайте в нём файл data.yaml. Поместите в этот файл данные, указанные в начале файла.
  9. В каталоге lib создайте файл dao.rb и разместите в нём модуль DAO. Создайте в нём метод для чтения информации из файла. Можно назвать его ::read_db.
  10. В каталоге lib создайте файл student.rb и разместите в нём класс Student. Определите методы для доступа и модификации полей данного класса.
  11. В каталоге lib создайте файл course.rb и разместите в нём класс Course. Определите методы для определения и получения оценки для определённого студента. Создайте итератор для обхода всех пар студент-оценка. Запрещено предоставлять доступ к переменной экземпляра, содержащей информацию об оценках.
  12. Создайте классы StudentRegistry и CourseRegistry, которые будут хранить в себе информацию о классах.
    • Создайте методы для добавления и удаления элементов из реестров.
    • Создайте итераторы для обхода содержимого рестра.
  13. Создайте класс Database, содержащий в себе ссылки на реестры студентов и курсов.
  14. Дополнительно. Подумайте о создании класса Grade, описывающего оценку для студента. Подумайте насколько эта сущность необходима для решения задач.
  15. Модифицируйте модуль DAO, чтобы он возвращал класс Database в качестве результата чтения данных из файла.
  16. Создайте модуль Input, в котором реализуйте методы для:
    • Ввода числа (оценки) со стандартного потока ввода. Метод должен внутри себя обрабатывать все некооректные ситуации и возвращать вещественное число, которое ввёл пользователь.
    • Выбора элемента из списка. Методу передаётся список вариантов, из которых должен выбрать пользователь, метод возвращает номер действия, которое выбрал пользователь. Метод должен внутри себя обрабатывать все некорректные ситуации и просить пользователя выбрать необходимое действие.
  17. Начнём реализацию первого сценария, отображения списка оценок с их средним баллом.
    • При создании объекта Core используйте модуль Dao для инициализации переменной экземпляра, хранящей ссылку на объект класса Database.
    • Отобразите пользователю меню со всеми действиями, которыми должна отрабатывать программу.
    • Создайте метод #show_courses в классе Core, который будет использовать итератор класса CourseRegistry для показа необходимой информации. В самом классе Core не должно содержаться никакой логики по вычислению значений.
    • Если пользователь выбрал первый пункт (отображение списка предметов), то необходимо вызвать созданный метод #show_courses.

Реализацию следующих сценариев делайте подобным образом, чтобы в классе Core не было никакой сложной предметной логики.