my_students 1.0.1
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 +7 -0
- data/lib/my_students/version.rb +5 -0
- data/lib/my_students.rb +10 -0
- data/lib/source/controllers/student_contact_form_controller.rb +40 -0
- data/lib/source/controllers/student_create_form_controller.rb +48 -0
- data/lib/source/controllers/student_edit_form_controller.rb +45 -0
- data/lib/source/controllers/student_git_form_controller.rb +40 -0
- data/lib/source/controllers/student_list_controller.rb +112 -0
- data/lib/source/gui/logic_window.rb +187 -0
- data/lib/source/gui/main_window.rb +26 -0
- data/lib/source/gui/student_create_form.rb +70 -0
- data/lib/source/gui/test.rb +32 -0
- data/lib/source/logger/logger_holder.rb +23 -0
- data/lib/source/models/student.rb +163 -0
- data/lib/source/models/student_short.rb +56 -0
- data/lib/source/repositories/containers/data_list.rb +67 -0
- data/lib/source/repositories/containers/data_list_student_short.rb +18 -0
- data/lib/source/repositories/containers/data_table.rb +38 -0
- data/lib/source/repositories/data_sources/strategy/student_list_json.rb +16 -0
- data/lib/source/repositories/data_sources/strategy/student_list_txt.rb +39 -0
- data/lib/source/repositories/data_sources/strategy/student_list_yaml.rb +17 -0
- data/lib/source/repositories/data_sources/student_list_base.rb +91 -0
- data/lib/source/repositories/data_sources/student_list_strategy.rb +12 -0
- data/lib/source/repositories/db_university.rb +28 -0
- data/lib/source/repositories/student_list.rb +40 -0
- data/lib/source/repositories/student_list_db_adapter.rb +75 -0
- data/lib/source/repositories/student_list_file_adapter.rb +42 -0
- data/my_students.gemspec +17 -0
- data/sig/my_students.rbs +4 -0
- metadata +85 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require_relative 'student_short'
|
|
5
|
+
|
|
6
|
+
class Student < StudentShort
|
|
7
|
+
# стандартные геттеры и сеттеры для класса
|
|
8
|
+
attr_writer :id
|
|
9
|
+
attr_reader :phone, :telegram, :email, :first_name, :paternal_name
|
|
10
|
+
|
|
11
|
+
# валидаТОР номера телефона
|
|
12
|
+
def self.valid_phone?(phone)
|
|
13
|
+
phone.match(/^\+?[7,8] ?\(?\d{3}\)?-?\d{3}-?\d{2}-?\d{2}$/)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# валидаТОР имени
|
|
17
|
+
def self.valid_name?(name)
|
|
18
|
+
name.match(/^[А-Я][а-я]+$/)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# валидаТОР профиля
|
|
22
|
+
def self.valid_account?(account)
|
|
23
|
+
account.match(/^@[A-Za-z0-9\-_]+$/)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# валидаТОР почты
|
|
27
|
+
def self.valid_email?(email)
|
|
28
|
+
email.match(/^[A-Za-z0-9\-_]+@[A-Za-z]+\.([A-Za-z]+\.)*[A-Za-z]+$/)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# стандартный конструктор
|
|
32
|
+
def initialize(last_name, first_name, paternal_name, id: nil, git: nil, phone: nil, email: nil, telegram: nil)
|
|
33
|
+
self.last_name = last_name
|
|
34
|
+
self.first_name = first_name
|
|
35
|
+
self.paternal_name = paternal_name
|
|
36
|
+
self.id = id
|
|
37
|
+
self.git = git
|
|
38
|
+
set_contacts(phone: phone, email: email, telegram: telegram)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# конструктор принимающий на вход хээээш
|
|
43
|
+
def self.from_hash(hash)
|
|
44
|
+
hash = hash.dup
|
|
45
|
+
raise ArgumentError, 'Missing fields: last_name, first_name, paternal_name' unless hash.key?(:first_name) && hash.key?(:last_name) && hash.key?(:paternal_name)
|
|
46
|
+
|
|
47
|
+
first_name = hash.delete(:first_name)
|
|
48
|
+
last_name = hash.delete(:last_name)
|
|
49
|
+
paternal_name = hash.delete(:paternal_name)
|
|
50
|
+
|
|
51
|
+
Student.new(last_name, first_name, paternal_name, **hash)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_hash
|
|
55
|
+
attrs = {}
|
|
56
|
+
%i[last_name first_name paternal_name id phone telegram email git].each do |attr|
|
|
57
|
+
attr_val = send(attr)
|
|
58
|
+
attrs[attr] = attr_val unless attr_val.nil?
|
|
59
|
+
end
|
|
60
|
+
attrs
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# конструктор из json-строки
|
|
64
|
+
def self.init_from_json(str)
|
|
65
|
+
params = JSON.parse(str, { symbolize_names: true })
|
|
66
|
+
from_hash(params)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
#сеттеры
|
|
70
|
+
def phone=(phone)
|
|
71
|
+
raise ArgumentError, "Incorrect value: phone=#{phone}!" if !phone.nil? && !Student.valid_phone?(phone)
|
|
72
|
+
|
|
73
|
+
@phone = phone
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def first_name=(first_name)
|
|
77
|
+
raise ArgumentError, "Incorrect value: first_name=#{first_name}!" if !first_name.nil? && !Student.valid_name?(first_name)
|
|
78
|
+
|
|
79
|
+
@first_name = first_name
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def last_name=(last_name)
|
|
83
|
+
raise ArgumentError, "Incorrect value: last_name=#{last_name}" if !last_name.nil? && !Student.valid_name?(last_name)
|
|
84
|
+
|
|
85
|
+
@last_name = last_name
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def paternal_name=(paternal_name)
|
|
89
|
+
raise ArgumentError, "Incorrect value: paternal_name=#{paternal_name}!" if !paternal_name.nil? && !Student.valid_name?(paternal_name)
|
|
90
|
+
|
|
91
|
+
@paternal_name = paternal_name
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def git=(git)
|
|
95
|
+
raise ArgumentError, "Incorrect value: git=#{git}!" if !git.nil? && !Student.valid_account?(git)
|
|
96
|
+
|
|
97
|
+
@git = git
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def telegram=(telegram)
|
|
101
|
+
raise ArgumentError, "Incorrect value: telegram=#{telegram}!" if !telegram.nil? && !Student.valid_account?(telegram)
|
|
102
|
+
|
|
103
|
+
@telegram = telegram
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def email=(email)
|
|
107
|
+
raise ArgumentError, "Incorrect value: email=#{email}!" if !email.nil? && !Student.valid_email?(email)
|
|
108
|
+
|
|
109
|
+
@email = email
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# метод возвращающий фамилию и инициалы у объекта
|
|
113
|
+
def last_name_and_initials
|
|
114
|
+
"#{last_name} #{first_name[0]}. #{paternal_name[0]}."
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# метод возвращающий краткую инф-ю об объекте
|
|
118
|
+
def short_info
|
|
119
|
+
info = {}
|
|
120
|
+
info[:last_name_and_initials] = last_name_and_initials
|
|
121
|
+
info[:contact] = contact
|
|
122
|
+
info[:git] = git
|
|
123
|
+
JSON.generate(info)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def set_contacts(phone: nil, telegram: nil, email: nil)
|
|
128
|
+
self.phone = phone if phone
|
|
129
|
+
self.telegram = telegram if telegram
|
|
130
|
+
self.email = email if email
|
|
131
|
+
@contact = contact
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# метод возвращающий представление объекта в виде строки
|
|
135
|
+
def to_s
|
|
136
|
+
result = "#{last_name} #{first_name} #{paternal_name}"
|
|
137
|
+
result += " id=#{id}" unless id.nil?
|
|
138
|
+
result += " phone=#{phone}" unless phone.nil?
|
|
139
|
+
result += " git=#{git}" unless git.nil?
|
|
140
|
+
result += " telegram=#{telegram}" unless telegram.nil?
|
|
141
|
+
result += " email=#{email}" unless email.nil?
|
|
142
|
+
result
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
|
|
147
|
+
# метод устанавливающий контакт
|
|
148
|
+
def contact
|
|
149
|
+
# return @contact = {phone: phone} unless phone.nil?
|
|
150
|
+
# return @contact = {telegram: telegram} unless telegram.nil?
|
|
151
|
+
# return @contact = {email: email} unless email.nil?
|
|
152
|
+
#
|
|
153
|
+
# nil
|
|
154
|
+
|
|
155
|
+
if phone
|
|
156
|
+
@contact = {type: :phone, value: phone}
|
|
157
|
+
elsif telegram
|
|
158
|
+
@contact = {type: :telegram, value: telegram}
|
|
159
|
+
elsif email
|
|
160
|
+
@contact = {type: :email, value: email}
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
class StudentShort
|
|
5
|
+
# стандартные геттеры для класса
|
|
6
|
+
attr_reader :id, :git, :contact, :last_name, :initials
|
|
7
|
+
|
|
8
|
+
# стандартный конструктор, принимающий аргументов экземпляр класса student
|
|
9
|
+
def initialize(student)
|
|
10
|
+
@id = student.id
|
|
11
|
+
|
|
12
|
+
@last_name = student.last_name
|
|
13
|
+
@initials = "#{student.first_name[0]}. #{student.paternal_name[0]}."
|
|
14
|
+
@git = student.git unless student.git.nil?
|
|
15
|
+
@contact = student.set_contacts(phone: student.phone, email: student.email, telegram: student.telegram)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# кастомный конструктор, принимающий на вход id и строку, которая содержит всю остальную инф-ю
|
|
19
|
+
def self.from_str(id, str)
|
|
20
|
+
result = JSON.parse(str)
|
|
21
|
+
raise ArgumentError, 'Missing fields: last_name, first_name, paternal_name' unless result.key?('first_name') &&
|
|
22
|
+
result.key?('last_name') && result.key?('paternal_name')
|
|
23
|
+
|
|
24
|
+
StudentShort.new(Student.new(result['last_name'],result['first_name'],result['paternal_name'],id: id,
|
|
25
|
+
phone: result['phone'], git: result['git'],
|
|
26
|
+
email: result['email'],telegram: result['telegram']))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# метод возвращающий фамилию и инициалы у объекта
|
|
30
|
+
def last_name_and_initials
|
|
31
|
+
"#{@last_name} #{@initials}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# метод возвращающий представление объекта в виде строки
|
|
35
|
+
def to_s
|
|
36
|
+
result = last_name_and_initials
|
|
37
|
+
result += " id= #{id} " unless id.nil?
|
|
38
|
+
result += contact unless contact.nil?
|
|
39
|
+
result
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# метод проверяющий наличие гита
|
|
43
|
+
def git?
|
|
44
|
+
!git.nil?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# метод проверяющий наличие контакта
|
|
48
|
+
def contact?
|
|
49
|
+
!contact.nil?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def validate
|
|
53
|
+
git? && contact?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'data_table'
|
|
3
|
+
|
|
4
|
+
class DataList
|
|
5
|
+
|
|
6
|
+
private_class_method :new
|
|
7
|
+
|
|
8
|
+
attr_writer :objects_list
|
|
9
|
+
|
|
10
|
+
def initialize(objects)
|
|
11
|
+
self.objects_list = objects
|
|
12
|
+
@observers = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_observer(observer)
|
|
16
|
+
@observers.append(observer)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def remove_observer(observer)
|
|
20
|
+
@observers.delete(observer)
|
|
21
|
+
end
|
|
22
|
+
def notify
|
|
23
|
+
@observers.each { |observer| observer.on_datalist_changed(get_data) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# добавить айди в выборку
|
|
27
|
+
def select_elem(number)
|
|
28
|
+
self.selected_object = number
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def selected_id
|
|
32
|
+
objects_list[selected_object].id
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# шаблон
|
|
36
|
+
def get_data
|
|
37
|
+
index_id=0
|
|
38
|
+
dt = objects_list.inject([]) do |res, object|
|
|
39
|
+
row=[index_id]
|
|
40
|
+
row.append(*table_fields(object))
|
|
41
|
+
index_id+=1
|
|
42
|
+
res<<row
|
|
43
|
+
end
|
|
44
|
+
DataTable.new(dt)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def replace_objects(objects)
|
|
49
|
+
self.objects_list = objects.dup
|
|
50
|
+
notify
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
protected
|
|
54
|
+
|
|
55
|
+
# должен быть реализован в детях
|
|
56
|
+
def get_names; end
|
|
57
|
+
|
|
58
|
+
# теперь этот метод необходимо переопределять у наследников(если я правильно понял принцип паттерна)
|
|
59
|
+
def table_fields(object)
|
|
60
|
+
[]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
attr_reader :objects_list
|
|
66
|
+
attr_accessor :selected_object
|
|
67
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'data_list'
|
|
4
|
+
class DataListStudentShort < DataList
|
|
5
|
+
public_class_method :new
|
|
6
|
+
|
|
7
|
+
# переопределенный метод из предка
|
|
8
|
+
def get_names
|
|
9
|
+
["last_name_and_initials", "git", "contact"]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
protected
|
|
13
|
+
|
|
14
|
+
# паблон шаттерн
|
|
15
|
+
def table_fields(object)
|
|
16
|
+
[object.last_name_and_initials, object.git, object.contact]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class DataTable
|
|
4
|
+
|
|
5
|
+
attr_reader :rows_count, :cols_count
|
|
6
|
+
|
|
7
|
+
def initialize(table)
|
|
8
|
+
|
|
9
|
+
self.rows_count = table.length
|
|
10
|
+
max_cols = 0
|
|
11
|
+
table.each do |row|
|
|
12
|
+
max_cols = row.length if row.size > max_cols
|
|
13
|
+
end
|
|
14
|
+
self.cols_count = max_cols
|
|
15
|
+
self.table = table
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get_item(row, col)
|
|
19
|
+
return nil if row >= rows_count || row.negative?
|
|
20
|
+
return nil if col >= cols_count || col.negative?
|
|
21
|
+
|
|
22
|
+
table[row][col]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_my_array
|
|
26
|
+
table.dup
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_s
|
|
30
|
+
table.map { |row| "[#{row.join(', ')}]" }.join("\n")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
attr_accessor :table
|
|
36
|
+
attr_writer :rows_count, :cols_count
|
|
37
|
+
|
|
38
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../student_list_strategy'
|
|
4
|
+
require 'json'
|
|
5
|
+
class StudentListJSON < StudentListStrategy
|
|
6
|
+
public_class_method :new
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def str_to_list(str)
|
|
10
|
+
JSON.parse(str, { symbolize_names: true })
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def list_to_str(list)
|
|
14
|
+
JSON.generate(list)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../student_list_strategy'
|
|
4
|
+
require 'json'
|
|
5
|
+
class StudentListTxt < StudentListStrategy
|
|
6
|
+
public_class_method :new
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def str_to_list(str)
|
|
10
|
+
transform_to_hashes(str.split("\n").map(&:chomp))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def list_to_str(list)
|
|
14
|
+
transform_to_string(list)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def transform_to_hashes(list_of_strings)
|
|
20
|
+
list_of_hashes = []
|
|
21
|
+
list_of_strings.each do |string|
|
|
22
|
+
string = string.gsub('"', "")
|
|
23
|
+
hash = {}
|
|
24
|
+
string.split(',').each do |attribute|
|
|
25
|
+
key, value = attribute.split(':').map(&:strip)
|
|
26
|
+
hash[key.to_sym] = value
|
|
27
|
+
end
|
|
28
|
+
list_of_hashes << hash
|
|
29
|
+
end
|
|
30
|
+
list_of_hashes
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def transform_to_string(hashes)
|
|
34
|
+
lines = hashes.map do |hash|
|
|
35
|
+
hash.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
|
|
36
|
+
end
|
|
37
|
+
lines.join("\n")
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../student_list_strategy'
|
|
4
|
+
require 'yaml'
|
|
5
|
+
|
|
6
|
+
class StudentListYaml<StudentListStrategy
|
|
7
|
+
public_class_method :new
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def str_to_list(str)
|
|
11
|
+
YAML.safe_load(str).map { |h| h.transform_keys(&:to_sym) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def list_to_str(hash_list)
|
|
15
|
+
hash_list.map { |h| h.transform_keys(&:to_s) }.to_yaml
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class StudentListBase
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
attr_writer :data_type
|
|
7
|
+
|
|
8
|
+
# конструктор
|
|
9
|
+
def initialize(data_type)
|
|
10
|
+
self.students = []
|
|
11
|
+
self.cur_id = 1
|
|
12
|
+
self.data_type = data_type
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# загрузка из файла
|
|
16
|
+
def load_from_file(file_path)
|
|
17
|
+
list = data_type.str_to_list(File.read(file_path))
|
|
18
|
+
self.students = list.map { |h| Student.from_hash(h) }
|
|
19
|
+
update_cur_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# выгрузка в файл
|
|
23
|
+
def save_to_file(file_path)
|
|
24
|
+
list = students.map(&:to_hash)
|
|
25
|
+
File.write(file_path, data_type.list_to_str(list))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# найти студента по айди
|
|
29
|
+
def student_by_id(student_id)
|
|
30
|
+
students.detect { |s| s.id == student_id }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# найти студента по фамилии и инциалам
|
|
34
|
+
def student_by_name(student_name)
|
|
35
|
+
students.filter { |s| s.last_name_and_initials == student_name }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Получить page по счету count элементов (страница начинается с 1)
|
|
39
|
+
def k_n_student_short_list(page, n, data_list)
|
|
40
|
+
page_list = students[(page-1)*n, n].map{|st| StudentShort.new(st)}
|
|
41
|
+
return DataListStudentShort.new(page_list) if data_list.nil?
|
|
42
|
+
|
|
43
|
+
data_list.replace_objects(page_list)
|
|
44
|
+
data_list
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# сортировка
|
|
48
|
+
def sorted
|
|
49
|
+
students.sort_by(&:last_name_and_initials)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# добавление студента
|
|
53
|
+
def add_student(student)
|
|
54
|
+
student.id = cur_id
|
|
55
|
+
students << student
|
|
56
|
+
self.cur_id += 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# замена студента
|
|
60
|
+
def replace_student(student_id, student)
|
|
61
|
+
idx = students.find_index { |s| s.id == student_id }
|
|
62
|
+
students[idx] = student
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# отчисление студента))
|
|
66
|
+
def remove_student(student_id)
|
|
67
|
+
students.reject! { |s| s.id == student_id }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# число студентов
|
|
71
|
+
def student_count
|
|
72
|
+
students.size
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
protected
|
|
77
|
+
|
|
78
|
+
attr_accessor :students, :cur_id
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
attr_reader :data_type
|
|
83
|
+
|
|
84
|
+
# Метод для обновлении информации в cur_id
|
|
85
|
+
def update_cur_id
|
|
86
|
+
self.cur_id = students.max_by(&:id).id.to_i + 1
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# чтобы никто мне ничего не трогал в списке студентов
|
|
90
|
+
|
|
91
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class DBUniversity
|
|
2
|
+
private_class_method :new
|
|
3
|
+
@instance_mutex = Mutex.new
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@client = SQLite3::Database.open '/Users/kirilltitov/RubymineProjects/ruby_labs/university.sqlite'
|
|
7
|
+
@client.results_as_hash = true
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.instance
|
|
11
|
+
return @instance if @instance
|
|
12
|
+
|
|
13
|
+
@instance_mutex.synchronize do
|
|
14
|
+
@instance ||= new
|
|
15
|
+
end
|
|
16
|
+
@instance
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def prepare_exec(statement, *params)
|
|
20
|
+
@client.prepare(statement).execute(*params)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def query(statement)
|
|
24
|
+
@client.query(statement)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class StudentList
|
|
4
|
+
|
|
5
|
+
# конструктор
|
|
6
|
+
def initialize(data_adapter)
|
|
7
|
+
@data_adapter = data_adapter
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# получить студента по id
|
|
11
|
+
def student_by_id(student_id)
|
|
12
|
+
@data_adapter.student_by_id(student_id)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
#добавление студента
|
|
17
|
+
def add_student(student)
|
|
18
|
+
@data_adapter.add_student(student)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#отчисление студента
|
|
22
|
+
def remove_student(student_id)
|
|
23
|
+
@data_adapter.remove_student(student_id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#замена студента
|
|
27
|
+
def replace_student(student_id, student)
|
|
28
|
+
@data_adapter.replace_student(student_id, student)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#подсчет количества студентов
|
|
32
|
+
def student_count
|
|
33
|
+
@data_adapter.student_count
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#получение n элементов k страницы
|
|
37
|
+
def k_n_student_short_list(k,n, data_list)
|
|
38
|
+
@data_adapter.k_n_student_short_list(k,n,data_list)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require_relative 'db_university'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'sqlite3'
|
|
4
|
+
class StudentListDbAdapter
|
|
5
|
+
|
|
6
|
+
# новый конструктор
|
|
7
|
+
def initialize
|
|
8
|
+
self.client = DBUniversity.instance
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def from_array_to_hash(arr)
|
|
12
|
+
attrs = {}
|
|
13
|
+
i=0
|
|
14
|
+
%i[id last_name first_name paternal_name phone telegram email git].each do |attr|
|
|
15
|
+
attrs[attr] = arr[i] unless arr[i].nil?
|
|
16
|
+
i=i+1
|
|
17
|
+
end
|
|
18
|
+
attrs
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# вернуть студента по ид
|
|
22
|
+
def student_by_id(student_id)
|
|
23
|
+
hash = client.prepare_exec('SELECT * FROM students WHERE id = ?',student_id).first
|
|
24
|
+
hash = from_array_to_hash(hash)
|
|
25
|
+
return nil if hash.nil?
|
|
26
|
+
|
|
27
|
+
Student.from_hash(hash)
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def k_n_student_short_list(k,n, data_list=nil)
|
|
32
|
+
|
|
33
|
+
offset = (k - 1) * n
|
|
34
|
+
students = client.prepare_exec('SELECT * FROM students LIMIT ?, ?', offset, n)
|
|
35
|
+
|
|
36
|
+
slice = students.map { |h|
|
|
37
|
+
h = h.transform_keys(&:to_sym)
|
|
38
|
+
StudentShort.new(Student.from_hash(h))
|
|
39
|
+
}
|
|
40
|
+
return DataListStudentShort.new(slice) if data_list.nil?
|
|
41
|
+
|
|
42
|
+
data_list.replace_objects(slice)
|
|
43
|
+
data_list
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# добавление студента
|
|
47
|
+
def add_student(student)
|
|
48
|
+
stmt = client.prepare_exec('insert into students (first_name, last_name, paternal_name, phone, telegram, email, git) VALUES (?, ?, ?, ?, ?, ?, ?)', *student_fields(student))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# отчисление студента
|
|
52
|
+
def remove_student(student_id)
|
|
53
|
+
client.prepare_exec('DELETE FROM students WHERE id = ?', student_id)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# обновление студента
|
|
57
|
+
def replace_student(student_id, student)
|
|
58
|
+
template = 'UPDATE students SET first_name=?, last_name=?, paternal_name=?, phone=?, telegram=?, email=?, git=? WHERE id=?'
|
|
59
|
+
client.prepare_exec(template, *student_fields(student), student_id)
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def student_count
|
|
64
|
+
client.query('SELECT COUNT(id) FROM students').next[0]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
attr_accessor :client
|
|
71
|
+
|
|
72
|
+
def student_fields(student)
|
|
73
|
+
[student.first_name, student.last_name, student.paternal_name, student.phone, student.telegram, student.email, student.git]
|
|
74
|
+
end
|
|
75
|
+
end
|