From d392be8d5d212c9c27c834a1af516dd84f54e4ed Mon Sep 17 00:00:00 2001 From: Artem Darius Weber Date: Sat, 14 Dec 2024 13:31:30 +0300 Subject: [PATCH] refactor: update Student class initialization and validation; add StudentRepository for file operations --- lab2/student.rb | 167 +++++++++++++++++-------------------- lab2/student_repository.rb | 39 +++++++++ 2 files changed, 117 insertions(+), 89 deletions(-) create mode 100644 lab2/student_repository.rb diff --git a/lab2/student.rb b/lab2/student.rb index 57d26a7..c9b1145 100644 --- a/lab2/student.rb +++ b/lab2/student.rb @@ -1,92 +1,81 @@ require_relative 'person' +require_relative 'contact' class Student < Person - attr_accessor :surname, :name, :patronymic - - def initialize(args = {}) - super(args) - @surname = args.fetch(:surname) - raise ArgumentError, "Invalid surname format: #{@surname}" unless self.class.valid_name?(@surname) - - @name = args.fetch(:name) - raise ArgumentError, "Invalid name format: #{@name}" unless self.class.valid_name?(@name) - - @patronymic = args.fetch(:patronymic) - raise ArgumentError, "Invalid patronymic format: #{@patronymic}" unless self.class.valid_name?(@patronymic) - - set_contacts( - phone: args[:phone], - telegram: args[:telegram], - email: args[:email] - ) - end - - def self.from_string(student_string) - parts = student_string.split('|').map(&:strip) - surname, name, patronymic = parts[0].split(' ') - id = parts[1].split(': ').last.to_i - phone = parts[2].split(': ').last - telegram = parts[3].split(': ').last - email = parts[4].split(': ').last - git = parts[5].split(': ').last - - new( - surname: surname, - name: name, - patronymic: patronymic, - id: id, - phone: phone, - telegram: telegram, - email: email, - git: git - ) - end - - def self.read_from_txt(file_path) - raise IOError, "File path is invalid or file does not exist: #{file_path}" unless File.exist?(file_path) - - students = [] - - File.foreach(file_path) do |line| - line.strip! - next if line.empty? - - begin - student = from_string(line) - students << student - rescue ArgumentError => e - puts "Error processing line: '#{line}'. Reason: #{e.message}" - end - end - - students - end - - def self.write_to_txt(file_path, students) - raise ArgumentError, "Expected an array of Student objects" unless students.is_a?(Array) && students.all? { |s| s.is_a?(Student) } - - File.open(file_path, 'w') do |file| - students.each do |student| - file.puts student.to_s - end - end - - puts "Data successfully written to #{file_path}" - rescue IOError => e - puts "An error occurred while writing to the file: #{e.message}" - end - - def surname_and_initials - "#{@surname} #{name[0]}.#{patronymic[0]}." - end - - def to_s - "#{@surname} #{@name} #{@patronymic} | ID: #{@id || 'N/A'} | " \ - "Phone: #{@phone || 'N/A'} | Telegram: #{@telegram || 'N/A'} | " \ - "Email: #{@email || 'N/A'} | Git: #{@git || 'N/A'}" - end - - def get_info - "#{surname_and_initials}, Git: #{git_info}, Contact: #{contact_info}" - end -end \ No newline at end of file + attr_accessor :surname, :name, :patronymic + + NAME_REGEX = /\A[А-Яа-яЁёA-Za-z\-]+\z/ + + def initialize(id:, git:, contact:, surname:, name:, patronymic:) + super(id: id, git: git, contact: contact) + @surname = surname + @name = name + @patronymic = patronymic + + validate_student + end + + def self.from_string(student_string) + parts = student_string.split('|').map(&:strip) + raise ArgumentError, 'Invalid student string format' if parts.size < 6 + + name_parts = parts[0].split(' ') + raise ArgumentError, 'Invalid name format' if name_parts.size != 3 + + surname, name, patronymic = name_parts + id = parts[1].split(': ').last + phone = parts[2].split(': ').last + telegram = parts[3].split(': ').last + email = parts[4].split(': ').last + git = parts[5].split(': ').last + + contact = Contact.new(phone: phone, telegram: telegram, email: email) + + new( + id: id, + git: git, + contact: contact, + surname: surname, + name: name, + patronymic: patronymic + ) + end + + def surname_and_initials + "#{@surname} #{name_initial(@name)}.#{patronymic_initial(@patronymic)}." + end + + def to_s + "#{@surname} #{@name} #{@patronymic} | ID: #{@id} | " \ + "Phone: #{@contact.phone || 'N/A'} | Telegram: #{@contact.telegram || 'N/A'} | " \ + "Email: #{@contact.email || 'N/A'} | Git: #{@git}" + end + + def get_info + "#{surname_and_initials}, Git: #{@git}, Contact: #{contact_info}" + end + + private + + def validate_student + raise ArgumentError, 'Surname is required' if @surname.nil? || @surname.strip.empty? + raise ArgumentError, 'Name is required' if @name.nil? || @name.strip.empty? + raise ArgumentError, 'Patronymic is required' if @patronymic.nil? || @patronymic.strip.empty? + + raise ArgumentError, "Invalid surname format: #{@surname}" unless valid_name?(@surname) + raise ArgumentError, "Invalid name format: #{@name}" unless valid_name?(@name) + raise ArgumentError, "Invalid patronymic format: #{@patronymic}" unless valid_name?(@patronymic) + end + + def valid_name?(name) + NAME_REGEX.match?(name) + end + + def name_initial(name) + name[0].upcase + end + + def patronymic_initial(patronymic) + patronymic[0].upcase + end +end diff --git a/lab2/student_repository.rb b/lab2/student_repository.rb new file mode 100644 index 0000000..9679409 --- /dev/null +++ b/lab2/student_repository.rb @@ -0,0 +1,39 @@ +require_relative 'student' + +class StudentRepository + def self.read_from_txt(file_path) + raise IOError, "File does not exist: #{file_path}" unless File.exist?(file_path) + + students = [] + + File.foreach(file_path) do |line| + line.strip! + next if line.empty? + + begin + student = Student.from_string(line) + students << student + rescue ArgumentError => e + puts "Error processing line: '#{line}'. Reason: #{e.message}" + end + end + + students + end + + def self.write_to_txt(file_path, students) + unless students.is_a?(Array) && students.all? { |s| s.is_a?(Student) } + raise ArgumentError, 'Expected an array of Student objects' + end + + File.open(file_path, 'w') do |file| + students.each do |student| + file.puts student.to_s + end + end + + puts "Data successfully written to #{file_path}" + rescue IOError => e + puts "An error occurred while writing to the file: #{e.message}" + end +end