shnaider_code 1.1.5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|