diff --git a/lab2/providers/persistence_strategy.rb b/lab2/providers/persistence_strategy.rb new file mode 100644 index 0000000..93d2961 --- /dev/null +++ b/lab2/providers/persistence_strategy.rb @@ -0,0 +1,9 @@ +module PersistenceStrategy + def load(filename) + raise NotImplementedError, "Метод load должен быть реализован в стратегии" + end + + def save(filename, students) + raise NotImplementedError, "Метод save должен быть реализован в стратегии" + end +end \ No newline at end of file diff --git a/lab2/providers/students_list.rb b/lab2/providers/students_list.rb new file mode 100644 index 0000000..9822db1 --- /dev/null +++ b/lab2/providers/students_list.rb @@ -0,0 +1,92 @@ +require_relative '../student' +require_relative '../student_short' +require_relative '../data_list_student_short' +require_relative '../data_table' + +class StudentsList + attr_reader :students + + def initialize(filename, persistence_strategy) + @filename = filename + @persistence_strategy = persistence_strategy + @students = [] + end + + # Загрузка студентов через выбранную стратегию. + def load + @students = @persistence_strategy.load(@filename) + self + end + + # Сохранение студентов через выбранную стратегию. + def save + @persistence_strategy.save(@filename, @students) + self + 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 + + # Добавление студента с автоматическим присвоением нового 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/providers/students_list_json.rb b/lab2/providers/students_list_json.rb index f681f28..7a47975 100644 --- a/lab2/providers/students_list_json.rb +++ b/lab2/providers/students_list_json.rb @@ -1,34 +1,33 @@ require 'json' require 'date' -require_relative 'students_list_base' require_relative '../student' +require_relative 'persistence_strategy' -class StudentsListJSON < StudentsListBase - def load_from_file - if File.exist?(@filename) - file_content = File.read(@filename) +class JSONPersistenceStrategy + include PersistenceStrategy + + def load(filename) + if File.exist?(filename) + file_content = File.read(filename) begin data = JSON.parse(file_content) - @students = data.map { |student_hash| hash_to_student(student_hash) } + data.map { |student_hash| hash_to_student(student_hash) } rescue JSON::ParserError => e warn "Ошибка парсинга JSON: #{e.message}" - @students = [] + [] end else - @students = [] + [] end - self end - def save_to_file - data = @students.map { |student| student_to_hash(student) } - File.open(@filename, 'w') do |file| + def save(filename, students) + data = students.map { |student| student_to_hash(student) } + File.open(filename, 'w') do |file| file.write(JSON.pretty_generate(data)) end - self rescue IOError => e warn "Ошибка при записи в файл: #{e.message}" - self end private diff --git a/lab2/providers/students_list_txt.rb b/lab2/providers/students_list_txt.rb index 5d87b06..f9ad757 100644 --- a/lab2/providers/students_list_txt.rb +++ b/lab2/providers/students_list_txt.rb @@ -1,11 +1,13 @@ -require_relative 'students_list_base' require_relative '../student' +require_relative 'persistence_strategy' -class StudentsListTXT < StudentsListBase - def load_from_file - if File.exist?(@filename) - File.open(@filename, 'r') do |file| - @students = file.each_line.map do |line| +class TXTPersistenceStrategy + include PersistenceStrategy + + def load(filename) + if File.exist?(filename) + File.open(filename, 'r') do |file| + file.each_line.map do |line| line.strip! next if line.empty? begin @@ -17,17 +19,15 @@ class StudentsListTXT < StudentsListBase end.compact end else - @students = [] + [] end - self end - def save_to_file - File.open(@filename, 'w') do |file| - @students.each do |student| + def save(filename, students) + File.open(filename, 'w') do |file| + students.each do |student| file.puts student.to_s end end - self end end diff --git a/lab2/providers/students_list_yaml.rb b/lab2/providers/students_list_yaml.rb index fb69463..aa7d68b 100644 --- a/lab2/providers/students_list_yaml.rb +++ b/lab2/providers/students_list_yaml.rb @@ -1,34 +1,32 @@ -# students_list_yaml.rb require 'yaml' require 'date' -require_relative 'students_list_base' require_relative '../student' +require_relative 'persistence_strategy' -class StudentsListYAML < StudentsListBase - def load_from_file - if File.exist?(@filename) +class YAMLPersistenceStrategy + include PersistenceStrategy + + def load(filename) + if File.exist?(filename) begin - data = YAML.load_file(@filename) - @students = data.map { |student_hash| hash_to_student(student_hash) } + data = YAML.load_file(filename) + data.map { |student_hash| hash_to_student(student_hash) } rescue StandardError => e warn "Ошибка при загрузке YAML: #{e.message}" - @students = [] + [] end else - @students = [] + [] end - self end - def save_to_file - data = @students.map { |student| student_to_hash(student) } - File.open(@filename, 'w') do |file| + def save(filename, students) + 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 private diff --git a/lab2/tests/test_students_list_json.rb b/lab2/tests/test_students_list_json.rb index f9e7d52..843c3a6 100644 --- a/lab2/tests/test_students_list_json.rb +++ b/lab2/tests/test_students_list_json.rb @@ -1,6 +1,7 @@ require 'minitest/autorun' require 'json' require 'date' +require_relative '../providers/students_list' require_relative '../providers/students_list_json' require_relative '../student' require_relative '../student_short' @@ -11,7 +12,7 @@ class TestStudentsListJSON < Minitest::Test def setup # Удаляем временный файл перед каждым тестом, если он существует File.delete(TEMP_FILE) if File.exist?(TEMP_FILE) - @students_list = StudentsListJSON.new(TEMP_FILE) + @students_list = StudentsList.new(TEMP_FILE, JSONPersistenceStrategy.new) # Создаём несколько объектов Student для тестирования @student1 = Student.new( @@ -61,11 +62,11 @@ class TestStudentsListJSON < Minitest::Test def test_save_and_load_from_file # Сохраняем текущий список в файл - @students_list.save_to_file + @students_list.save # Создаём новый объект, который загрузит данные из файла - new_list = StudentsListJSON.new(TEMP_FILE) - new_list.load_from_file + new_list = StudentsList.new(TEMP_FILE, JSONPersistenceStrategy.new) + new_list.load # Проверяем, что количество студентов совпадает assert_equal @students_list.get_student_short_count, new_list.get_student_short_count diff --git a/lab2/tests/test_students_list_txt.rb b/lab2/tests/test_students_list_txt.rb index 6f78904..fd0bd8b 100644 --- a/lab2/tests/test_students_list_txt.rb +++ b/lab2/tests/test_students_list_txt.rb @@ -1,11 +1,13 @@ require 'date' +require_relative '../providers/students_list' require_relative '../providers/students_list_txt' require_relative '../student' require_relative '../student_short' def run_tests filename = 'students_test.txt' - students_list = StudentsListTXT.new(filename) + # Инициализируем список студентов с TXT-стратегией + students_list = StudentsList.new(filename, TXTPersistenceStrategy.new) # 1. Добавление студентов. Передаём временный ID '0', который будет заменён. student1 = Student.new( @@ -23,8 +25,8 @@ def run_tests puts "Добавленные студенты:\n#{students_list.students.map(&:to_s).join("\n")}" # 2. Сохранение и загрузка из файла - students_list.save_to_file - students_list.load_from_file + students_list.save + students_list.load puts "\nЗагруженные студенты из файла:\n#{students_list.students.map(&:to_s).join("\n")}" diff --git a/lab2/tests/test_students_list_yaml.rb b/lab2/tests/test_students_list_yaml.rb index f41e681..c155ed1 100644 --- a/lab2/tests/test_students_list_yaml.rb +++ b/lab2/tests/test_students_list_yaml.rb @@ -1,6 +1,7 @@ require 'minitest/autorun' require 'yaml' require 'date' +require_relative '../providers/students_list' require_relative '../providers/students_list_yaml' require_relative '../student' require_relative '../student_short' @@ -11,7 +12,7 @@ class TestStudentsListYAML < Minitest::Test def setup # Удаляем временный файл перед каждым тестом, если он существует File.delete(TEMP_FILE) if File.exist?(TEMP_FILE) - @students_list = StudentsListYAML.new(TEMP_FILE) + @students_list = StudentsList.new(TEMP_FILE, YAMLPersistenceStrategy.new) # Создаём несколько объектов Student для тестирования @student1 = Student.new( @@ -61,11 +62,11 @@ class TestStudentsListYAML < Minitest::Test def test_save_and_load_from_file # Сохраняем список в YAML-файл - @students_list.save_to_file + @students_list.save # Создаём новый объект, который загрузит данные из файла - new_list = StudentsListYAML.new(TEMP_FILE) - new_list.load_from_file + new_list = StudentsList.new(TEMP_FILE, YAMLPersistenceStrategy.new) + new_list.load # Проверяем, что количество студентов совпадает assert_equal @students_list.get_student_short_count, new_list.get_student_short_count