From c586e3ed937328902119eda7b17d24a3fd77f8c6 Mon Sep 17 00:00:00 2001 From: Artem Darius Weber Date: Fri, 14 Feb 2025 23:19:57 +0300 Subject: [PATCH] refactor: rename student list classes for consistency and improve code structure (LAB 4 TASK 4) --- lab2/students_list_base.rb | 89 +++++++++++++++++++++++++ lab2/students_list_json.rb | 91 +------------------------- lab2/students_list_txt.rb | 94 ++------------------------- lab2/students_list_yaml.rb | 90 +------------------------ lab2/tests/test_students_list_json.rb | 5 +- lab2/tests/test_students_list_txt.rb | 6 +- lab2/tests/test_students_list_yaml.rb | 5 +- 7 files changed, 105 insertions(+), 275 deletions(-) create mode 100644 lab2/students_list_base.rb diff --git a/lab2/students_list_base.rb b/lab2/students_list_base.rb new file mode 100644 index 0000000..8a96e46 --- /dev/null +++ b/lab2/students_list_base.rb @@ -0,0 +1,89 @@ +require_relative 'student' +require_relative 'student_short' +require_relative 'data_list_student_short' +require_relative 'data_table' + +class StudentsListBase + attr_reader :students + + def initialize(filename) + @filename = filename + @students = [] + end + + # Абстрактный метод для загрузки данных. + def load_from_file + raise NotImplementedError, "Метод load_from_file должен быть реализован в подклассе" + end + + # Абстрактный метод для сохранения данных. + def save_to_file + raise NotImplementedError, "Метод save_to_file должен быть реализован в подклассе" + end + + # Получить объект Student по ID. + def get_student_by_id(id) + @students.find { |s| s.id.to_s == id.to_s } + end + + # Получить список из k студентов (страница n) в виде объекта DataList. + 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. + 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. + 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 +end diff --git a/lab2/students_list_json.rb b/lab2/students_list_json.rb index f355863..13d8897 100644 --- a/lab2/students_list_json.rb +++ b/lab2/students_list_json.rb @@ -1,20 +1,9 @@ require 'json' require 'date' +require_relative 'students_list_base' require_relative 'student' -require_relative 'student_short' -require_relative 'data_list_student_short' -require_relative 'data_table' -class Students_list_JSON - attr_reader :students - - def initialize(filename) - @filename = filename - @students = [] - end - - # Чтение всех значений из JSON-файла. - # Файл должен содержать массив хэшей, где каждый хэш представляет студента. +class StudentsListJSON < StudentsListBase def load_from_file if File.exist?(@filename) file_content = File.read(@filename) @@ -31,8 +20,6 @@ class Students_list_JSON self end - # Запись всех значений в JSON-файл. - # Преобразуем каждый объект Student в хэш. def save_to_file data = @students.map { |student| student_to_hash(student) } File.open(@filename, 'w') do |file| @@ -44,81 +31,8 @@ class Students_list_JSON self end - # Получить объект Student по ID. - def get_student_by_id(id) - @students.find { |s| s.id.to_s == id.to_s } - end - - # Получить список из k студентов (на "странице" n) в виде DataList объекта. - # При этом сначала список студентов сортируется по ФамилияИнициалы, - # а затем из него выбирается срез нужного размера. - # Если передан существующий объект data_list, то его список обновляется. - 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). - # Новый ID вычисляется как (максимальный существующий id + 1) или 1, если список пуст. - 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 в хэш для записи в JSON. def student_to_hash(student) { 'id' => student.id, @@ -133,7 +47,6 @@ class Students_list_JSON } end - # Преобразование хэша в объект Student. def hash_to_student(hash) Student.new( id: hash['id'], diff --git a/lab2/students_list_txt.rb b/lab2/students_list_txt.rb index 4f3f931..f7a2527 100644 --- a/lab2/students_list_txt.rb +++ b/lab2/students_list_txt.rb @@ -1,21 +1,12 @@ -require_relative 'data_list_student_short' +require_relative 'students_list_base' +require_relative 'student' -class Students_list_txt - attr_reader :students - - def initialize(filename) - @filename = filename - @students = [] - end - - # Чтение всех значений из файла. - # Предполагается, что каждая строка файла соответствует формату, - # который понимает метод Student.from_string. +class StudentsListTXT < StudentsListBase def load_from_file if File.exist?(@filename) File.open(@filename, 'r') do |file| @students = file.each_line.map do |line| - line = line.strip + line.strip! next if line.empty? begin Student.from_string(line) @@ -31,8 +22,6 @@ class Students_list_txt self end - # Запись всех значений в файл. - # Для записи используется формат, возвращаемый методом to_s у объекта Student. def save_to_file File.open(@filename, 'w') do |file| @students.each do |student| @@ -41,79 +30,4 @@ class Students_list_txt end self end - - # Получить объект класса Student по ID. - def get_student_by_id(id) - @students.find { |s| s.id.to_s == id.to_s } - end - - # Получить список из k элементов, начиная с (n-1)*k-й записи, в виде объекта DataList. - # Если передан существующий объект data_list, то его список обновляется. - # При выборке сначала выполняется сортировка по фамилии и инициалам. - # - # Пример: k = 20, n = 2 даст вторую «страницу» из 20 элементов. - 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] || [] - # Преобразуем объекты Student в StudentShort - 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). - # Новый ID вычисляется как (максимальный существующий id + 1) или 1, если список пуст. - 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 end diff --git a/lab2/students_list_yaml.rb b/lab2/students_list_yaml.rb index 3aac431..ef759f1 100644 --- a/lab2/students_list_yaml.rb +++ b/lab2/students_list_yaml.rb @@ -1,20 +1,10 @@ +# students_list_yaml.rb require 'yaml' require 'date' +require_relative 'students_list_base' 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-файла. - # Файл должен содержать массив хэшей, каждый из которых представляет студента. +class StudentsListYAML < StudentsListBase def load_from_file if File.exist?(@filename) begin @@ -30,8 +20,6 @@ class Students_list_YAML self end - # Запись всех значений в YAML-файл. - # Каждый объект Student преобразуется в хэш. def save_to_file data = @students.map { |student| student_to_hash(student) } File.open(@filename, 'w') do |file| @@ -43,79 +31,8 @@ class Students_list_YAML 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, @@ -130,7 +47,6 @@ class Students_list_YAML } end - # Преобразование хэша в объект Student. def hash_to_student(hash) Student.new( id: hash['id'], diff --git a/lab2/tests/test_students_list_json.rb b/lab2/tests/test_students_list_json.rb index 23ab75f..730a01b 100644 --- a/lab2/tests/test_students_list_json.rb +++ b/lab2/tests/test_students_list_json.rb @@ -1,4 +1,3 @@ -# test_students_list_json.rb require 'minitest/autorun' require 'json' require 'date' @@ -12,7 +11,7 @@ class TestStudentsListJSON < Minitest::Test def setup # Удаляем временный файл перед каждым тестом, если он существует File.delete(TEMP_FILE) if File.exist?(TEMP_FILE) - @students_list = Students_list_JSON.new(TEMP_FILE) + @students_list = StudentsListJSON.new(TEMP_FILE) # Создаём несколько объектов Student для тестирования @student1 = Student.new( @@ -65,7 +64,7 @@ class TestStudentsListJSON < Minitest::Test @students_list.save_to_file # Создаём новый объект, который загрузит данные из файла - new_list = Students_list_JSON.new(TEMP_FILE) + new_list = StudentsListJSON.new(TEMP_FILE) new_list.load_from_file # Проверяем, что количество студентов совпадает diff --git a/lab2/tests/test_students_list_txt.rb b/lab2/tests/test_students_list_txt.rb index 1c7397d..a240a8c 100644 --- a/lab2/tests/test_students_list_txt.rb +++ b/lab2/tests/test_students_list_txt.rb @@ -5,7 +5,7 @@ require_relative '../student_short' def run_tests filename = 'students_test.txt' - students_list = Students_list_txt.new(filename) + students_list = StudentsListTXT.new(filename) # 1. Добавление студентов. Передаём временный ID '0', который будет заменён. student1 = Student.new( @@ -32,11 +32,11 @@ def run_tests student = students_list.get_student_by_id(1) puts "\nНайден студент по ID 1: #{student}" - # 4. Получение "страничного" списка StudentShort (1 элемент на страницу, 1-я страница) + # 4. Получение \"страничного\" списка StudentShort (1 элемент на страницу, 1-я страница) short_list = students_list.get_k_n_student_short_list(1, 1) puts "\nПервая страница списка StudentShort:" short_list.get_data.rows_count.times do |row| - puts short_list.get_data.item(row, 1) # выводим Фамилия и инициалы + puts short_list.get_data.item(row, 1) # выводим Фамилию и инициалы end # 5. Обновление студента diff --git a/lab2/tests/test_students_list_yaml.rb b/lab2/tests/test_students_list_yaml.rb index d1e6cf5..d18dfa9 100644 --- a/lab2/tests/test_students_list_yaml.rb +++ b/lab2/tests/test_students_list_yaml.rb @@ -1,4 +1,3 @@ -# test_students_list_yaml.rb require 'minitest/autorun' require 'yaml' require 'date' @@ -12,7 +11,7 @@ class TestStudentsListYAML < Minitest::Test def setup # Удаляем временный файл перед каждым тестом, если он существует File.delete(TEMP_FILE) if File.exist?(TEMP_FILE) - @students_list = Students_list_YAML.new(TEMP_FILE) + @students_list = StudentsListYAML.new(TEMP_FILE) # Создаём несколько объектов Student для тестирования @student1 = Student.new( @@ -65,7 +64,7 @@ class TestStudentsListYAML < Minitest::Test @students_list.save_to_file # Создаём новый объект, который загрузит данные из файла - new_list = Students_list_YAML.new(TEMP_FILE) + new_list = StudentsListYAML.new(TEMP_FILE) new_list.load_from_file # Проверяем, что количество студентов совпадает