Создание собственных классов
Целью данного занятия является закрепление полученных знаний о создании классов на языке 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 и все его сообщения должны быть исправлены.
Предлагаемый подход к решению задачи
- Создайте каталог, в котором далее будете разрабатывать приложение.
- Создайте подкаталоги
bin
иlib
в созданном каталоге. - Установите джем
bundler
и инициализируйте с помощью Bundler его конфигурационный файл. - Добавьте в качестве зависимости и установие джем
rubocop
. После выполнения каждого шага необходимо запускатьrubocop
и исправлять код в соответствии с его замечаниями. После их исправления переходите к следующему шагу. - Создайте конфигурационный файл для Rubocop и поместите его в корень проекта.
- В каталоге
lib
создайте файлcore.rb
.- В данном файле создайте класс
Core
и определите в нём метод#run
. - Данный метод должен печатать приветствие на стандартный поток вывода. Приветствие нужно только лишь для того, чтобы вы смогли убедиться, что метод работает.
- В данном файле создайте класс
- В каталоге
bin
создайте файлapplication.rb
.- В данном файле подключите файл
core
, создайте экземпляр классаCore
и вызовите его метод#run
. - Больше никакого кода в данный файл добавлять не надо, а всю разработку надо вести в каталоге
lib
.
- В данном файле подключите файл
- В корне проекта созадйте каталог
data
и создайте в нём файлdata.yaml
. Поместите в этот файл данные, указанные в начале файла. - В каталоге
lib
создайте файлdao.rb
и разместите в нём модульDAO
. Создайте в нём метод для чтения информации из файла. Можно назвать его::read_db
. - В каталоге
lib
создайте файлstudent.rb
и разместите в нём классStudent
. Определите методы для доступа и модификации полей данного класса. - В каталоге
lib
создайте файлcourse.rb
и разместите в нём классCourse
. Определите методы для определения и получения оценки для определённого студента. Создайте итератор для обхода всех пар студент-оценка. Запрещено предоставлять доступ к переменной экземпляра, содержащей информацию об оценках. - Создайте классы
StudentRegistry
иCourseRegistry
, которые будут хранить в себе информацию о классах.- Создайте методы для добавления и удаления элементов из реестров.
- Создайте итераторы для обхода содержимого рестра.
- Создайте класс
Database
, содержащий в себе ссылки на реестры студентов и курсов. - Дополнительно. Подумайте о создании класса
Grade
, описывающего оценку для студента. Подумайте насколько эта сущность необходима для решения задач. - Модифицируйте модуль
DAO
, чтобы он возвращал классDatabase
в качестве результата чтения данных из файла. - Создайте модуль
Input
, в котором реализуйте методы для:- Ввода числа (оценки) со стандартного потока ввода. Метод должен внутри себя обрабатывать все некооректные ситуации и возвращать вещественное число, которое ввёл пользователь.
- Выбора элемента из списка. Методу передаётся список вариантов, из которых должен выбрать пользователь, метод возвращает номер действия, которое выбрал пользователь. Метод должен внутри себя обрабатывать все некорректные ситуации и просить пользователя выбрать необходимое действие.
- Начнём реализацию первого сценария, отображения списка оценок с их средним баллом.
- При создании объекта
Core
используйте модульDao
для инициализации переменной экземпляра, хранящей ссылку на объект классаDatabase
. - Отобразите пользователю меню со всеми действиями, которыми должна отрабатывать программу.
- Создайте метод
#show_courses
в классеCore
, который будет использовать итератор классаCourseRegistry
для показа необходимой информации. В самом классеCore
не должно содержаться никакой логики по вычислению значений. - Если пользователь выбрал первый пункт (отображение списка предметов), то необходимо вызвать созданный метод
#show_courses
.
- При создании объекта
Реализацию следующих сценариев делайте подобным образом, чтобы в классе Core
не было никакой сложной предметной логики.
Работа с YAML-документами
В отличие от библиотеки csv
библиотека yaml
ориентирована на работу со строками, а не с файлами. Это сделано сделано в перую очередь вииду того, что YAML-документы могут быть не только считаны из файла, но также получены другими путями, например через сетевое взаимодействие. Для разрабатываемого приложения это означает, что вам сначала необходимо будет считать содержимое файла в строку, а затем воспользоваться методами библиотеки yaml
.
Для считывания всех данных из файла необходимо воспользоваться методом #read
класса File
. То есть необходимо сначала создать объект класса файл, передав конструктору в качестве аргумента путь к файлу, а затем прочитать всё содержимое файла с помощью данного метода. Желательно перед открытием и считыванием информации из файла проверить, что такой файл существует с помощью метода #exist?
. После окончания считывания информации из файла не забудьте закрыть данный файл, используя метод #close
.
После успешного считывания данных из файла необходимо преобразовать строку в Ruby-объекты. Для этого используется метод .load
. Методу в качестве аргумента передаётся строка, а он возвращает созданные Ruby-объекты. Для обратного преобразования использутся метод .dump
модуля YAML
или метод .to_yaml
, который определяется у базового объекта Object
.
Если вы хотите более глубоко разобраться с возможностями библиотеки по работе с YAML-документами, тогда вам необходимо обратиться к официальной документации джема psych
.