shnaider_code 1.1.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/shnaider_code/version.rb +1 -1
- data/lib/source/attr_limited_regex_accessor.rb +43 -0
- data/lib/source/controllers/create_student_controller.rb +8 -0
- data/lib/source/controllers/edit_student_controller.rb +10 -0
- data/lib/source/controllers/view_controller.rb +106 -0
- data/lib/source/data_construct_pattern/data_construct_pattarn.rb +25 -0
- data/lib/source/data_list.rb +59 -0
- data/lib/source/data_list_student_short.rb +28 -0
- data/lib/source/data_table.rb +21 -0
- data/lib/source/database/scripts/create_table.sql +10 -0
- data/lib/source/database/scripts/fill_data.sql +14 -0
- data/lib/source/database/students_db.rb +78 -0
- data/lib/source/database/students_list_db.rb +36 -0
- data/lib/source/student/abstract_student.rb +26 -0
- data/lib/source/student/student.rb +120 -0
- data/lib/source/student/student_short.rb +59 -0
- data/lib/source/student_list_format.rb +50 -0
- data/lib/source/students_list.rb +43 -0
- data/lib/source/students_list_adapter.rb +89 -0
- data/lib/source/students_list_format_strategy.rb +59 -0
- data/lib/source/students_tests.rb +72 -0
- data/shnaider_code.gemspec +4 -6
- metadata +25 -33
- data/CHANGELOG.md +0 -5
- data/CODE_OF_CONDUCT.md +0 -84
- data/Documentation.md +0 -33
- data/Gemfile +0 -13
- data/Gemfile.lock +0 -92
- data/lib/source/controllers/student_input_form/student_input_form_controller_create.rb +0 -68
- data/lib/source/controllers/student_input_form/student_input_form_controller_edit.rb +0 -78
- data/lib/source/controllers/tab_students_controller.rb +0 -104
- data/lib/source/db_config/config.example.yaml +0 -5
- data/lib/source/db_config/migrations/001_create_table_student.sql +0 -12
- data/lib/source/db_config/mock_data/fill_student.sql +0 -6
- data/lib/source/models/student.rb +0 -125
- data/lib/source/models/student_base.rb +0 -128
- data/lib/source/models/student_short.rb +0 -58
- data/lib/source/repositories/adapters/db_source_adapter.rb +0 -54
- data/lib/source/repositories/adapters/file_source_adapter.rb +0 -37
- data/lib/source/repositories/containers/data_list.rb +0 -74
- data/lib/source/repositories/containers/data_list_student_short.rb +0 -18
- data/lib/source/repositories/containers/data_table.rb +0 -35
- data/lib/source/repositories/data_sources/db_data_source.rb +0 -35
- data/lib/source/repositories/data_sources/file_data_source.rb +0 -77
- data/lib/source/repositories/data_sources/transformers/data_transformer_base.rb +0 -15
- data/lib/source/repositories/data_sources/transformers/data_transformer_json.rb +0 -16
- data/lib/source/repositories/data_sources/transformers/data_transformer_yaml.rb +0 -16
- data/lib/source/repositories/student_repository.rb +0 -37
- data/lib/source/util/logger_holder.rb +0 -29
- data/shnaider_code-1.1.4.gem +0 -0
- data/sig/shnaider_code.rbs +0 -4
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require './LabStudents/util/logger_holder'
|
4
|
-
require 'win32api'
|
5
|
-
|
6
|
-
##
|
7
|
-
# Контроллер для модального окна создания студента
|
8
|
-
|
9
|
-
class StudentInputFormControllerCreate
|
10
|
-
def initialize(parent_controller)
|
11
|
-
@parent_controller = parent_controller
|
12
|
-
LoggerHolder.instance.debug('StudentInputFormControllerCreate: initialized')
|
13
|
-
end
|
14
|
-
|
15
|
-
def set_view(view)
|
16
|
-
@view = view
|
17
|
-
LoggerHolder.instance.debug('StudentInputFormControllerCreate: view set')
|
18
|
-
end
|
19
|
-
|
20
|
-
##
|
21
|
-
# Вызывается из view после ее создания
|
22
|
-
|
23
|
-
def on_view_created
|
24
|
-
begin
|
25
|
-
@student_rep = StudentRepository.new(DBSourceAdapter.new)
|
26
|
-
rescue Mysql2::Error::ConnectionError => e
|
27
|
-
on_db_conn_error(e)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
##
|
32
|
-
# Обработать данные из полей и добавить студента
|
33
|
-
|
34
|
-
def process_fields(fields)
|
35
|
-
begin
|
36
|
-
last_name = fields.delete(:last_name)
|
37
|
-
first_name = fields.delete(:first_name)
|
38
|
-
father_name = fields.delete(:father_name)
|
39
|
-
|
40
|
-
return if last_name.nil? || first_name.nil? || father_name.nil?
|
41
|
-
|
42
|
-
student = Student.new(last_name, first_name, father_name, **fields)
|
43
|
-
|
44
|
-
LoggerHolder.instance.debug('StudentInputFormControllerCreate: adding student to DB')
|
45
|
-
|
46
|
-
@student_rep.add_student(student)
|
47
|
-
|
48
|
-
@view.close
|
49
|
-
rescue ArgumentError => e
|
50
|
-
LoggerHolder.instance.debug("StudentInputFormControllerCreate: wrong fields: #{e.message}")
|
51
|
-
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
52
|
-
api.call(0, e.message, 'Error', 0)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
##
|
59
|
-
# Обработчик ошибки подключения к БД
|
60
|
-
|
61
|
-
def on_db_conn_error(error)
|
62
|
-
LoggerHolder.instance.debug('StudentInputFormControllerCreate: DB connection error:')
|
63
|
-
LoggerHolder.instance.error(error.message)
|
64
|
-
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
65
|
-
api.call(0, "No connection to DB", "Error", 0)
|
66
|
-
@view.close
|
67
|
-
end
|
68
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require './LabStudents/util/logger_holder'
|
4
|
-
require 'win32api'
|
5
|
-
|
6
|
-
##
|
7
|
-
# Контроллер для модального окна изменения студента
|
8
|
-
|
9
|
-
class StudentInputFormControllerEdit
|
10
|
-
def initialize(parent_controller, existing_student_id)
|
11
|
-
@parent_controller = parent_controller
|
12
|
-
@existing_student_id = existing_student_id
|
13
|
-
LoggerHolder.instance.debug('StudentInputFormControllerEdit: initialized')
|
14
|
-
end
|
15
|
-
|
16
|
-
def set_view(view)
|
17
|
-
@view = view
|
18
|
-
LoggerHolder.instance.debug('StudentInputFormControllerEdit: view set')
|
19
|
-
end
|
20
|
-
|
21
|
-
##
|
22
|
-
# Вызывается из view после ее создания
|
23
|
-
|
24
|
-
def on_view_created
|
25
|
-
begin
|
26
|
-
@student_rep = StudentRepository.new(DBSourceAdapter.new)
|
27
|
-
rescue Mysql2::Error::ConnectionError => e
|
28
|
-
on_db_conn_error(e)
|
29
|
-
end
|
30
|
-
@existing_student = @student_rep.student_by_id(@existing_student_id)
|
31
|
-
@view.make_readonly(:git, :telegram, :email, :phone)
|
32
|
-
populate_fields(@existing_student)
|
33
|
-
end
|
34
|
-
|
35
|
-
##
|
36
|
-
# Заполнить имеющиеся данные о студенте
|
37
|
-
|
38
|
-
def populate_fields(student)
|
39
|
-
@view.set_value(:last_name, student.last_name)
|
40
|
-
@view.set_value(:first_name, student.first_name)
|
41
|
-
@view.set_value(:father_name, student.father_name)
|
42
|
-
@view.set_value(:git, student.git)
|
43
|
-
@view.set_value(:telegram, student.telegram)
|
44
|
-
@view.set_value(:email, student.email)
|
45
|
-
@view.set_value(:phone, student.phone)
|
46
|
-
end
|
47
|
-
|
48
|
-
##
|
49
|
-
# Обработать данные из полей и добавить студента
|
50
|
-
|
51
|
-
def process_fields(fields)
|
52
|
-
begin
|
53
|
-
new_student = Student.from_hash(fields)
|
54
|
-
|
55
|
-
LoggerHolder.instance.debug('StudentInputFormControllerEdit: replacing student in DB')
|
56
|
-
|
57
|
-
@student_rep.replace_student(@existing_student_id, new_student)
|
58
|
-
|
59
|
-
@view.close
|
60
|
-
rescue ArgumentError => e
|
61
|
-
LoggerHolder.instance.debug("StudentInputFormControllerEdit: wrong fields: #{e.message}")
|
62
|
-
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
63
|
-
api.call(0, e.message, 'Error', 0)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
##
|
70
|
-
# Обработчик ошибки подключения к БД
|
71
|
-
def on_db_conn_error(error)
|
72
|
-
LoggerHolder.instance.debug('StudentInputFormControllerEdit: DB connection error:')
|
73
|
-
LoggerHolder.instance.error(error.message)
|
74
|
-
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
75
|
-
api.call(0, "No connection to DB", "Error", 0)
|
76
|
-
@view.close
|
77
|
-
end
|
78
|
-
end
|
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require './LabStudents/views/main_window'
|
4
|
-
require './LabStudents/repositories/student_repository'
|
5
|
-
require './LabStudents/repositories/adapters/db_source_adapter'
|
6
|
-
require './LabStudents/repositories/containers/data_list_student_short'
|
7
|
-
require './LabStudents/views/student_input_form'
|
8
|
-
require './LabStudents/controllers/student_input_form/student_input_form_controller_create'
|
9
|
-
require './LabStudents/controllers/student_input_form/student_input_form_controller_edit'
|
10
|
-
require './LabStudents/util/logger_holder'
|
11
|
-
require 'win32api'
|
12
|
-
|
13
|
-
##
|
14
|
-
# Контроллер для вкладки со списком студентов
|
15
|
-
|
16
|
-
class TabStudentsController
|
17
|
-
def initialize(view)
|
18
|
-
LoggerHolder.instance.debug('TabStudentsController: init start')
|
19
|
-
@view = view
|
20
|
-
@data_list = DataListStudentShort.new([])
|
21
|
-
@data_list.add_listener(@view)
|
22
|
-
LoggerHolder.instance.debug('TabStudentsController: init done')
|
23
|
-
end
|
24
|
-
|
25
|
-
##
|
26
|
-
# Вызывается из view после ее создания
|
27
|
-
|
28
|
-
def on_view_created
|
29
|
-
begin
|
30
|
-
@student_rep = StudentRepository.new(DBSourceAdapter.new)
|
31
|
-
LoggerHolder.instance.debug('TabStudentsController: created student repository')
|
32
|
-
rescue Mysql2::Error::ConnectionError => e
|
33
|
-
on_db_conn_error(e)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
##
|
39
|
-
# Показать модальное окно с добавлением студента
|
40
|
-
|
41
|
-
def show_modal_add
|
42
|
-
LoggerHolder.instance.debug('TabStudentsController: showing modal (add)')
|
43
|
-
controller = StudentInputFormControllerCreate.new(self)
|
44
|
-
view = StudentInputForm.new(controller)
|
45
|
-
controller.set_view(view)
|
46
|
-
view.create.show
|
47
|
-
end
|
48
|
-
|
49
|
-
##
|
50
|
-
# Показать модальное окно с изменением выделенного студента
|
51
|
-
|
52
|
-
def show_modal_edit(current_page, per_page, selected_row)
|
53
|
-
LoggerHolder.instance.debug('TabStudentsController: showing modal (edit)')
|
54
|
-
student_num = (current_page - 1) * per_page + selected_row
|
55
|
-
@data_list.select_element(student_num)
|
56
|
-
student_id = @data_list.selected_id
|
57
|
-
controller = StudentInputFormControllerEdit.new(self, student_id)
|
58
|
-
view = StudentInputForm.new(controller)
|
59
|
-
controller.set_view(view)
|
60
|
-
view.create.show
|
61
|
-
end
|
62
|
-
|
63
|
-
##
|
64
|
-
# Удалить выбранного студента
|
65
|
-
|
66
|
-
def delete_selected(current_page, per_page, selected_row)
|
67
|
-
begin
|
68
|
-
LoggerHolder.instance.debug('TabStudentsController: deleting selected student')
|
69
|
-
student_num = (current_page - 1) * per_page + selected_row
|
70
|
-
@data_list.select_element(student_num)
|
71
|
-
student_id = @data_list.selected_id
|
72
|
-
@student_rep.remove_student(student_id)
|
73
|
-
rescue Mysql2::Error::ConnectionError => e
|
74
|
-
on_db_conn_error(e)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
##
|
79
|
-
# Обновить данные в таблице студентов
|
80
|
-
|
81
|
-
def refresh_data(page, per_page)
|
82
|
-
begin
|
83
|
-
LoggerHolder.instance.debug('TabStudentsController: refreshing data...')
|
84
|
-
@data_list = @student_rep.paginated_short_students(page, per_page, @data_list)
|
85
|
-
@view.update_student_count(@student_rep.student_count)
|
86
|
-
rescue Mysql2::Error::ConnectionError => e
|
87
|
-
on_db_conn_error(e)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
##
|
94
|
-
# Обработчик ошибки подключения к БД
|
95
|
-
|
96
|
-
def on_db_conn_error(error)
|
97
|
-
LoggerHolder.instance.error('TabStudentsController: DB connection error:')
|
98
|
-
LoggerHolder.instance.error(error.message)
|
99
|
-
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
100
|
-
api.call(0, "No connection to DB", "Error", 0)
|
101
|
-
# TODO: Возможность переключения на JSON помимо exit
|
102
|
-
exit(false)
|
103
|
-
end
|
104
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
create table student (
|
2
|
-
id int auto_increment,
|
3
|
-
last_name varchar(128) not null,
|
4
|
-
first_name varchar(128) not null,
|
5
|
-
father_name varchar(128) not null,
|
6
|
-
phone varchar(20) null,
|
7
|
-
telegram varchar(100) null,
|
8
|
-
email varchar(100) null,
|
9
|
-
git varchar(100) null,
|
10
|
-
constraint student_pk
|
11
|
-
primary key (id)
|
12
|
-
);
|
@@ -1,6 +0,0 @@
|
|
1
|
-
insert into student(last_name, first_name, father_name, phone, telegram, email, git) values
|
2
|
-
('Тимофеев', 'Иван', 'Георгиевич', '79517532585', NULL, 'timka@mail.ru', NULL),
|
3
|
-
('Кот', 'Александр', 'Дмитриевич', NULL, 'prettykitty', 'kot@bk.ru', 'kotkotkot'),
|
4
|
-
('Симонов', 'Аркадий', 'Олегович', '79998881487', 'simark', 'arksim@gmail.com', NULL),
|
5
|
-
('Балбесов', 'Никита', 'Никитович', '79180005577', 'balnik', NULL, 'nikitos_b'),
|
6
|
-
('Титов', 'Артур', 'Николаевич', '79990805051', 'narot', 'aptyp@narod.ru', 'bot_waasabi');
|
@@ -1,125 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
require_relative 'student_base'
|
5
|
-
|
6
|
-
##
|
7
|
-
# Модель студента
|
8
|
-
|
9
|
-
class Student < StudentBase
|
10
|
-
public_class_method :new
|
11
|
-
|
12
|
-
##
|
13
|
-
# Конструктор из Hash. Ключи являются символами
|
14
|
-
def self.from_hash(hash)
|
15
|
-
hash = hash.dup
|
16
|
-
raise ArgumentError, 'Fields required: fist_name, last_name, father_name' unless hash.key?(:first_name) && hash.key?(:last_name) && hash.key?(:father_name)
|
17
|
-
|
18
|
-
first_name = hash.delete(:first_name)
|
19
|
-
last_name = hash.delete(:last_name)
|
20
|
-
father_name = hash.delete(:father_name)
|
21
|
-
|
22
|
-
Student.new(last_name, first_name, father_name, **hash)
|
23
|
-
end
|
24
|
-
|
25
|
-
##
|
26
|
-
# Конструктор из JSON строки
|
27
|
-
|
28
|
-
def self.from_json_str(str)
|
29
|
-
params = JSON.parse(str, { symbolize_names: true })
|
30
|
-
from_hash(params)
|
31
|
-
end
|
32
|
-
|
33
|
-
public :phone, :telegram, :email, 'id=', 'phone=', 'telegram=', 'email=', 'git='
|
34
|
-
|
35
|
-
attr_reader :last_name, :first_name, :father_name
|
36
|
-
|
37
|
-
##
|
38
|
-
# Стандартный конструктор. Принимает: Фамилия, Имя, Отчество, а также именованные параметры для предка
|
39
|
-
def initialize(last_name, first_name, father_name, **options)
|
40
|
-
self.last_name = last_name
|
41
|
-
self.first_name = first_name
|
42
|
-
self.father_name = father_name
|
43
|
-
super(**options)
|
44
|
-
end
|
45
|
-
|
46
|
-
def last_name=(new_last_name)
|
47
|
-
raise ArgumentError, "Invalid argument: last_name=#{new_last_name}" unless Student.valid_name?(new_last_name)
|
48
|
-
|
49
|
-
@last_name = new_last_name
|
50
|
-
end
|
51
|
-
|
52
|
-
def first_name=(new_first_name)
|
53
|
-
raise ArgumentError, "Invalid argument: first_name=#{new_first_name}" unless Student.valid_name?(new_first_name)
|
54
|
-
|
55
|
-
@first_name = new_first_name
|
56
|
-
end
|
57
|
-
|
58
|
-
def father_name=(new_father_name)
|
59
|
-
raise ArgumentError, "Invalid argument: father_name=#{new_father_name}" unless Student.valid_name?(new_father_name)
|
60
|
-
|
61
|
-
@father_name = new_father_name
|
62
|
-
end
|
63
|
-
|
64
|
-
##
|
65
|
-
# Сеттер для массовой установки контактов
|
66
|
-
|
67
|
-
def set_contacts(phone: nil, telegram: nil, email: nil)
|
68
|
-
self.phone = phone if phone
|
69
|
-
self.telegram = telegram if telegram
|
70
|
-
self.email = email if email
|
71
|
-
end
|
72
|
-
|
73
|
-
##
|
74
|
-
# Вернуть фамилию и инициалы в виде строки "Фамилия И. О."
|
75
|
-
|
76
|
-
def last_name_and_initials
|
77
|
-
"#{last_name} #{first_name[0]}. #{father_name[0]}."
|
78
|
-
end
|
79
|
-
|
80
|
-
##
|
81
|
-
# Краткая информация о пользователе в виде JSON строки.
|
82
|
-
# Поля:
|
83
|
-
# last_name_and_initials - Фамилия и инициалы в виде "Фамилия И. О."
|
84
|
-
# contact - Приоритетный доступный контакт в виде хеша (StudentBase#short_contact)
|
85
|
-
# git - Имя пользователя на гите
|
86
|
-
|
87
|
-
def short_info
|
88
|
-
info = {}
|
89
|
-
info[:last_name_and_initials] = last_name_and_initials
|
90
|
-
info[:contact] = short_contact
|
91
|
-
info[:git] = git
|
92
|
-
JSON.generate(info)
|
93
|
-
end
|
94
|
-
|
95
|
-
##
|
96
|
-
# Преобразование студента в строку
|
97
|
-
|
98
|
-
def to_s
|
99
|
-
result = "#{last_name} #{first_name} #{father_name}"
|
100
|
-
%i[id phone telegram email git].each do |attr|
|
101
|
-
attr_val = send(attr)
|
102
|
-
result += ", #{attr}=#{attr_val}" unless attr_val.nil?
|
103
|
-
end
|
104
|
-
result
|
105
|
-
end
|
106
|
-
|
107
|
-
##
|
108
|
-
# Преобразование студента в хеш. Поля являются ключами
|
109
|
-
|
110
|
-
def to_hash
|
111
|
-
attrs = {}
|
112
|
-
%i[last_name first_name father_name id phone telegram email git].each do |attr|
|
113
|
-
attr_val = send(attr)
|
114
|
-
attrs[attr] = attr_val unless attr_val.nil?
|
115
|
-
end
|
116
|
-
attrs
|
117
|
-
end
|
118
|
-
|
119
|
-
##
|
120
|
-
# Преобразование студента в JSON строку.
|
121
|
-
|
122
|
-
def to_json_str
|
123
|
-
JSON.generate(to_hash)
|
124
|
-
end
|
125
|
-
end
|
@@ -1,128 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
##
|
4
|
-
# Абстрактный класс с базовым описанием студента
|
5
|
-
|
6
|
-
class StudentBase
|
7
|
-
private_class_method :new
|
8
|
-
|
9
|
-
##
|
10
|
-
# Валидация имени (также применимо к фамилии и отчеству)
|
11
|
-
|
12
|
-
def self.valid_name?(name)
|
13
|
-
name.match(/(^[А-Я][а-я]+$)|(^[A-Z][a-z]+$)/)
|
14
|
-
end
|
15
|
-
|
16
|
-
##
|
17
|
-
# Валидация номера телефона
|
18
|
-
|
19
|
-
def self.valid_phone?(phone)
|
20
|
-
phone.match(/^\+?[78] ?[(-]?\d{3} ?[)-]?[ -]?\d{3}[ -]?\d{2}[ -]?\d{2}$/)
|
21
|
-
end
|
22
|
-
|
23
|
-
##
|
24
|
-
# Валидация имени профиля пользователя
|
25
|
-
|
26
|
-
def self.valid_profile_name?(profile_name)
|
27
|
-
profile_name.match(/^[a-zA-Z0-9_.]+$/)
|
28
|
-
end
|
29
|
-
|
30
|
-
##
|
31
|
-
# Валидация email
|
32
|
-
|
33
|
-
def self.valid_email?(email)
|
34
|
-
email.match(/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/)
|
35
|
-
end
|
36
|
-
|
37
|
-
protected
|
38
|
-
|
39
|
-
attr_writer :id
|
40
|
-
attr_reader :phone, :telegram, :email
|
41
|
-
|
42
|
-
public
|
43
|
-
|
44
|
-
attr_reader :id, :git
|
45
|
-
|
46
|
-
##
|
47
|
-
# Стандартный конструктор. Принимает именованные параметры:
|
48
|
-
# id - Id студента
|
49
|
-
# phone - Телефон
|
50
|
-
# telegram - Ник в телеграме
|
51
|
-
# email - Электронная почта
|
52
|
-
# git - Ник на гите
|
53
|
-
|
54
|
-
def initialize(id: nil, phone: nil, telegram: nil, email: nil, git: nil)
|
55
|
-
self.id = id
|
56
|
-
self.phone = phone
|
57
|
-
self.telegram = telegram
|
58
|
-
self.email = email
|
59
|
-
self.git = git
|
60
|
-
end
|
61
|
-
|
62
|
-
##
|
63
|
-
# Возвращает первый доступный контакт пользователя в виде хеша.
|
64
|
-
# Пример: {type: :telegram, value: 'xoxolovelylove'}
|
65
|
-
|
66
|
-
def short_contact
|
67
|
-
contact = {}
|
68
|
-
%i[telegram email phone].each do |attr|
|
69
|
-
attr_val = send(attr)
|
70
|
-
next if attr_val.nil?
|
71
|
-
|
72
|
-
contact[:type] = attr
|
73
|
-
contact[:value] = attr_val
|
74
|
-
return contact
|
75
|
-
end
|
76
|
-
|
77
|
-
nil
|
78
|
-
end
|
79
|
-
|
80
|
-
protected
|
81
|
-
|
82
|
-
def phone=(new_phone)
|
83
|
-
raise ArgumentError, "Invalid argument: phone=#{new_phone}" unless new_phone.nil? || StudentBase.valid_phone?(new_phone)
|
84
|
-
|
85
|
-
@phone = new_phone
|
86
|
-
end
|
87
|
-
|
88
|
-
def telegram=(new_telegram)
|
89
|
-
raise ArgumentError, "Invalid argument: telegram=#{new_telegram}" unless new_telegram.nil? || StudentBase.valid_profile_name?(new_telegram)
|
90
|
-
|
91
|
-
@telegram = new_telegram
|
92
|
-
end
|
93
|
-
|
94
|
-
def git=(new_git)
|
95
|
-
raise ArgumentError, "Invalid argument: git=#{new_git}" unless new_git.nil? || StudentBase.valid_profile_name?(new_git)
|
96
|
-
|
97
|
-
@git = new_git
|
98
|
-
end
|
99
|
-
|
100
|
-
def email=(new_email)
|
101
|
-
raise ArgumentError, "Invalid argument: email=#{new_email}" unless new_email.nil? || StudentBase.valid_email?(new_email)
|
102
|
-
|
103
|
-
@email = new_email
|
104
|
-
end
|
105
|
-
|
106
|
-
public
|
107
|
-
|
108
|
-
##
|
109
|
-
# Возвращает true, если у студента есть хотя бы один из контактов
|
110
|
-
|
111
|
-
def has_contacts?
|
112
|
-
!phone.nil? || !telegram.nil? || !email.nil?
|
113
|
-
end
|
114
|
-
|
115
|
-
##
|
116
|
-
# Возвращает true, если у студента есть гит
|
117
|
-
|
118
|
-
def has_git?
|
119
|
-
!git.nil?
|
120
|
-
end
|
121
|
-
|
122
|
-
##
|
123
|
-
# Возвращает true, если у студента есть хотя бы один из контактов и гит
|
124
|
-
|
125
|
-
def valid?
|
126
|
-
has_contacts? && has_git?
|
127
|
-
end
|
128
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
##
|
4
|
-
# Модель с краткой информацией о студенте
|
5
|
-
|
6
|
-
class StudentShort < StudentBase
|
7
|
-
public_class_method :new
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
attr_writer :last_name_and_initials, :contact
|
12
|
-
|
13
|
-
public
|
14
|
-
|
15
|
-
attr_reader :last_name_and_initials, :contact
|
16
|
-
|
17
|
-
##
|
18
|
-
# Конструктор из объекта класса Student
|
19
|
-
|
20
|
-
def self.from_student(student)
|
21
|
-
raise ArgumentError, 'Student ID is required' if student.id.nil?
|
22
|
-
|
23
|
-
StudentShort.new(student.id, student.short_info)
|
24
|
-
end
|
25
|
-
|
26
|
-
##
|
27
|
-
# Стандартный конструктор. Принимает:
|
28
|
-
# id - Числовой id студента
|
29
|
-
# info_str - JSON строка с полями last_name_and_initials (обязательно), contact, git, а также полями базового класса
|
30
|
-
|
31
|
-
def initialize(id, info_str)
|
32
|
-
params = JSON.parse(info_str, { symbolize_names: true })
|
33
|
-
raise ArgumentError, 'Fields required: last_name_and_initials' if !params.key?(:last_name_and_initials) || params[:last_name_and_initials].nil?
|
34
|
-
|
35
|
-
self.id = id
|
36
|
-
self.last_name_and_initials = params[:last_name_and_initials]
|
37
|
-
self.contact = params[:contact]
|
38
|
-
self.git = params[:git]
|
39
|
-
|
40
|
-
options = {}
|
41
|
-
options[:id] = id
|
42
|
-
options[:git] = git
|
43
|
-
options[contact[:type].to_sym] = contact[:value] if contact
|
44
|
-
super(**options)
|
45
|
-
end
|
46
|
-
|
47
|
-
##
|
48
|
-
# Преобразование объекта в строку
|
49
|
-
|
50
|
-
def to_s
|
51
|
-
result = last_name_and_initials
|
52
|
-
%i[id contact git].each do |attr|
|
53
|
-
attr_val = send(attr)
|
54
|
-
result += ", #{attr}=#{attr_val}" unless attr_val.nil?
|
55
|
-
end
|
56
|
-
result
|
57
|
-
end
|
58
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require './LabStudents/repositories/data_sources/db_data_source'
|
4
|
-
require './LabStudents/models/student'
|
5
|
-
require './LabStudents/models/student_short'
|
6
|
-
require './LabStudents/repositories/containers/data_list_student_short'
|
7
|
-
|
8
|
-
class DBSourceAdapter
|
9
|
-
def initialize
|
10
|
-
@db = DBDataSource.instance
|
11
|
-
end
|
12
|
-
|
13
|
-
def student_by_id(student_id)
|
14
|
-
hash = @db.prepare_exec('SELECT * FROM student WHERE id = ?', student_id).first
|
15
|
-
return nil if hash.nil?
|
16
|
-
|
17
|
-
Student.from_hash(hash)
|
18
|
-
end
|
19
|
-
|
20
|
-
def paginated_short_students(page, count, existing_data_list = nil)
|
21
|
-
offset = (page - 1) * count
|
22
|
-
students = @db.prepare_exec('SELECT * FROM student LIMIT ?, ?', offset, count)
|
23
|
-
slice = students.map { |h| StudentShort.from_student(Student.from_hash(h)) }
|
24
|
-
return DataListStudentShort.new(slice) if existing_data_list.nil?
|
25
|
-
|
26
|
-
existing_data_list.replace_objects(slice)
|
27
|
-
existing_data_list
|
28
|
-
end
|
29
|
-
|
30
|
-
def add_student(student)
|
31
|
-
template = 'INSERT INTO student(last_name, first_name, father_name, phone, telegram, email, git) VALUES (?, ?, ?, ?, ?, ?, ?)'
|
32
|
-
@db.prepare_exec(template, *student_fields(student))
|
33
|
-
@db.query('SELECT LAST_INSERT_ID()').first.first[1]
|
34
|
-
end
|
35
|
-
|
36
|
-
def replace_student(student_id, student)
|
37
|
-
template = 'UPDATE student SET last_name=?, first_name=?, father_name=?, phone=?, telegram=?, email=?, git=? WHERE id=?'
|
38
|
-
@db.prepare_exec(template, *student_fields(student), student_id)
|
39
|
-
end
|
40
|
-
|
41
|
-
def remove_student(student_id)
|
42
|
-
@db.prepare_exec('DELETE FROM student WHERE id = ?', student_id)
|
43
|
-
end
|
44
|
-
|
45
|
-
def student_count
|
46
|
-
@db.query('SELECT COUNT(id) FROM student').first.first[1]
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def student_fields(student)
|
52
|
-
[student.last_name, student.first_name, student.father_name, student.phone, student.telegram, student.email, student.git]
|
53
|
-
end
|
54
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class FileSourceAdapter
|
4
|
-
def initialize(data_transformer, file_path)
|
5
|
-
@file_path = file_path
|
6
|
-
@file_source = FileDataSource.new(data_transformer)
|
7
|
-
@file_source.load_from_file(file_path)
|
8
|
-
end
|
9
|
-
|
10
|
-
def student_by_id(student_id)
|
11
|
-
@file_source.student_by_id(student_id)
|
12
|
-
end
|
13
|
-
|
14
|
-
def paginated_short_students(page, count, existing_data_list = nil)
|
15
|
-
@file_source.paginated_short_students(page, count, existing_data_list)
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_student(student)
|
19
|
-
added_id = @file_source.add_student(student)
|
20
|
-
@file_source.save_to_file(@file_path)
|
21
|
-
added_id
|
22
|
-
end
|
23
|
-
|
24
|
-
def replace_student(student_id, student)
|
25
|
-
@file_source.replace_student(student_id, student)
|
26
|
-
@file_source.save_to_file(@file_path)
|
27
|
-
end
|
28
|
-
|
29
|
-
def remove_student(student_id)
|
30
|
-
@file_source.remove_student(student_id)
|
31
|
-
@file_source.save_to_file(@file_path)
|
32
|
-
end
|
33
|
-
|
34
|
-
def student_count
|
35
|
-
@file_source.student_count
|
36
|
-
end
|
37
|
-
end
|