feat: add Students_list_YAML class for YAML data handling and student management

lab4
Artem-Darius Weber 2 months ago
parent e969c49903
commit 9f98ff8eed

@ -0,0 +1,147 @@
require 'yaml'
require 'date'
require_relative 'student'
require_relative 'student_short'
require_relative 'data_list_student_short'
require_relative 'data_table'
class Students_list_YAML
attr_reader :students
def initialize(filename)
@filename = filename
@students = []
end
# Чтение всех значений из YAML-файла.
# Файл должен содержать массив хэшей, каждый из которых представляет студента.
def load_from_file
if File.exist?(@filename)
begin
data = YAML.load_file(@filename)
@students = data.map { |student_hash| hash_to_student(student_hash) }
rescue StandardError => e
warn "Ошибка при загрузке YAML: #{e.message}"
@students = []
end
else
@students = []
end
self
end
# Запись всех значений в YAML-файл.
# Каждый объект Student преобразуется в хэш.
def save_to_file
data = @students.map { |student| student_to_hash(student) }
File.open(@filename, 'w') do |file|
file.write(data.to_yaml)
end
self
rescue IOError => e
warn "Ошибка при записи в YAML: #{e.message}"
self
end
# Получить объект Student по ID.
def get_student_by_id(id)
@students.find { |s| s.id.to_s == id.to_s }
end
# Получить список из k студентов (страница n) в виде объекта DataList.
# Сначала список сортируется по ФамилияИнициалы, затем выбирается нужный срез.
# Результат преобразуется в объекты StudentShort.
def get_k_n_student_short_list(k, n, data_list = nil)
start_index = (n - 1) * k
sorted_students = @students.sort_by { |s| s.surname_initials }
selected_students = sorted_students[start_index, k] || []
short_objects = selected_students.map { |s| StudentShort.from_student(s) }
if data_list && data_list.is_a?(DataList)
if data_list.respond_to?(:items=)
data_list.items = short_objects
else
data_list = DataListStudentShort.new(short_objects)
end
data_list
else
DataListStudentShort.new(short_objects)
end
end
# Сортировать список студентов по ФамилияИнициалы.
def sort_students!
@students.sort_by! { |s| s.surname_initials }
end
# Добавить объект Student в список (при добавлении формируется новый ID).
def add_student(student)
new_id = if @students.empty?
1
else
max_id = @students.map { |s| s.id.to_i }.max
max_id + 1
end
student.id = new_id.to_s
@students << student
student
end
# Заменить элемент списка по ID.
# Если элемент найден, новый объект получает тот же ID.
def update_student_by_id(id, new_student)
index = @students.find_index { |s| s.id.to_s == id.to_s }
if index
new_student.id = @students[index].id
@students[index] = new_student
true
else
false
end
end
# Удалить элемент списка по ID.
# Возвращает true, если удаление прошло успешно.
def delete_student_by_id(id)
initial_count = @students.size
@students.reject! { |s| s.id.to_s == id.to_s }
initial_count != @students.size
end
# Получить количество студентов в списке.
def get_student_short_count
@students.size
end
private
# Преобразование объекта Student в хэш для записи в YAML.
def student_to_hash(student)
{
'id' => student.id,
'git' => student.git,
'surname' => student.surname,
'name' => student.name,
'patronymic' => student.patronymic,
'birth_date' => student.birth_date.to_s,
'phone' => student.phone,
'telegram' => student.telegram,
'email' => student.email
}
end
# Преобразование хэша в объект Student.
def hash_to_student(hash)
Student.new(
id: hash['id'],
git: hash['git'],
surname: hash['surname'],
name: hash['name'],
patronymic: hash['patronymic'],
birth_date: Date.parse(hash['birth_date']),
phone: hash['phone'],
telegram: hash['telegram'],
email: hash['email']
)
end
end

@ -0,0 +1,165 @@
# test_students_list_yaml.rb
require 'minitest/autorun'
require 'yaml'
require 'date'
require_relative '../students_list_yaml'
require_relative '../student'
require_relative '../student_short'
class TestStudentsListYAML < Minitest::Test
TEMP_FILE = 'temp_students.yaml'
def setup
# Удаляем временный файл перед каждым тестом, если он существует
File.delete(TEMP_FILE) if File.exist?(TEMP_FILE)
@students_list = Students_list_YAML.new(TEMP_FILE)
# Создаём несколько объектов Student для тестирования
@student1 = Student.new(
id: "1",
git: "https://github.com/test1",
surname: "Иванов",
name: "Иван",
patronymic: "Иванович",
birth_date: Date.new(2000, 1, 1),
phone: "+123456789",
telegram: "@test1",
email: "test1@example.com"
)
@student2 = Student.new(
id: "2",
git: "https://github.com/test2",
surname: "Петров",
name: "Пётр",
patronymic: "Петрович",
birth_date: Date.new(1999, 2, 2),
phone: "+987654321",
telegram: "@test2",
email: "test2@example.com"
)
@student3 = Student.new(
id: "3",
git: "https://github.com/test3",
surname: "Сидоров",
name: "Сидор",
patronymic: "Сидорович",
birth_date: Date.new(1998, 3, 3),
phone: "+192837465",
telegram: "@test3",
email: "test3@example.com"
)
# Добавляем студентов в список (при добавлении формируется новый ID)
@students_list.add_student(@student1)
@students_list.add_student(@student2)
@students_list.add_student(@student3)
end
def teardown
# Удаляем временный файл после выполнения тестов
File.delete(TEMP_FILE) if File.exist?(TEMP_FILE)
end
def test_save_and_load_from_file
# Сохраняем список в YAML-файл
@students_list.save_to_file
# Создаём новый объект, который загрузит данные из файла
new_list = Students_list_YAML.new(TEMP_FILE)
new_list.load_from_file
# Проверяем, что количество студентов совпадает
assert_equal @students_list.get_student_short_count, new_list.get_student_short_count
# Проверяем, что фамилии и инициалы студентов совпадают
original_names = @students_list.students.map(&:surname_initials).sort
loaded_names = new_list.students.map(&:surname_initials).sort
assert_equal original_names, loaded_names
end
def test_get_student_by_id
# Поиск студента по ID "1"
student = @students_list.get_student_by_id("1")
refute_nil student
assert_equal "Иванов И.И.", student.surname_initials
end
def test_get_k_n_student_short_list
# Получаем первую "страницу" из 2-х студентов
data_list = @students_list.get_k_n_student_short_list(2, 1)
# Ожидаем, что DataList содержит 2 записи
assert_equal 2, data_list.get_data.rows_count
# Проверяем, что столбец с Фамилией и инициалами содержит корректное значение
first_row = data_list.get_data.item(0, 1)
refute_nil first_row
assert_match(/[А-ЯЁ][а-яё]+ [А-Я]\./, first_row)
end
def test_sort_students!
# Перемешиваем порядок студентов и выполняем сортировку
@students_list.students.shuffle!
@students_list.sort_students!
sorted_names = @students_list.students.map(&:surname_initials)
# Проверяем, что список отсортирован лексикографически
assert_equal sorted_names.sort, sorted_names
end
def test_add_student
new_student = Student.new(
id: "0", # ID будет перезаписан
git: "https://github.com/test4",
surname: "Алексеев",
name: "Алексей",
patronymic: "Алексеевич",
birth_date: Date.new(2001, 4, 4),
phone: "+111222333",
telegram: "@test4",
email: "test4@example.com"
)
added_student = @students_list.add_student(new_student)
# Новый ID должен быть равен (максимальный существующий id + 1)
expected_id = (@students_list.students.map { |s| s.id.to_i }.max).to_s
assert_equal expected_id, added_student.id
assert_equal 4, @students_list.get_student_short_count
end
def test_update_student_by_id
updated_student = Student.new(
id: "0", # ID будет перезаписан
git: "https://github.com/updated",
surname: "Обновлённый",
name: "Студент",
patronymic: "Тестович",
birth_date: Date.new(2002, 5, 5),
phone: "+444555666",
telegram: "@updated",
email: "updated@example.com"
)
# Обновляем студента с ID "2"
result = @students_list.update_student_by_id("2", updated_student)
assert result
student = @students_list.get_student_by_id("2")
refute_nil student
assert_equal "Обновлённый С.Т.", student.surname_initials
assert_equal "https://github.com/updated", student.git
end
def test_delete_student_by_id
# Удаляем студента с ID "1"
result = @students_list.delete_student_by_id("1")
assert result
# Проверяем, что студент с ID "1" отсутствует
student = @students_list.get_student_by_id("1")
assert_nil student
# Количество студентов должно уменьшиться
assert_equal 2, @students_list.get_student_short_count
end
def test_get_student_short_count
assert_equal 3, @students_list.get_student_short_count
end
end
Loading…
Cancel
Save