mvcStudentXD 0.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -1
- data/lib/Student_list.rb +65 -0
- data/lib/adapters/student_list_adapter.rb +95 -0
- data/lib/containers/Data_list.rb +66 -0
- data/lib/containers/Data_list_student_short.rb +17 -0
- data/lib/containers/Data_table.rb +25 -0
- data/lib/converters/Converter.rb +11 -0
- data/lib/converters/Converter_json.rb +14 -0
- data/lib/converters/Converter_txt.rb +26 -0
- data/lib/converters/Converter_yaml.rb +14 -0
- data/lib/database/scripts/create_table.sql +10 -0
- data/lib/database/scripts/insert_data.sql +4 -0
- data/lib/database/student_list_db.rb +41 -0
- data/lib/database/students_db.rb +79 -0
- data/lib/model/Student.rb +106 -0
- data/lib/model/StudentBase.rb +50 -0
- data/lib/model/Student_short.rb +39 -0
- data/lib/mvcStudentXD/version.rb +1 -1
- data/lib/student_edit_form_controller.rb +63 -0
- data/lib/student_input_form.rb +71 -0
- data/lib/student_input_form_controller.rb +56 -0
- data/lib/student_list_adv.rb +35 -0
- data/lib/student_list_controller.rb +81 -0
- data/mvcStudentXD.gemspec +38 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5edf4f3f16bbfe82ed1302ffd8ec980a7cc0531faac61609e3cd2ae2b8abbeeb
|
4
|
+
data.tar.gz: d621edb76de6e5c4b7b3f27798e428fa8ba571f25a6e90408d27a8eef24923c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c59b1615e8e6f6255f071690609df5ccb14ab45b18c42a75fc656a2fac4df5314de05bb1e2fd0eb4efc998a3973e554cb680610125b675801f46d4ff1abd3f0a
|
7
|
+
data.tar.gz: 710895761936a9a5c215a39931872661ca8ddfb9537565ba8ef63736f8d3548b1a5691539d528b1789def5abb93157b806b114e08b51dbee1fa375a56de390ba
|
data/Gemfile
CHANGED
data/lib/Student_list.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
class StudentList
|
2
|
+
private
|
3
|
+
attr_accessor :students, :gen_id, :typer
|
4
|
+
|
5
|
+
public
|
6
|
+
def initialize(typer)
|
7
|
+
self.students = []
|
8
|
+
self.gen_id = students.count + 1
|
9
|
+
self.typer = typer
|
10
|
+
end
|
11
|
+
|
12
|
+
def read_file(file_path)
|
13
|
+
raise ArgumentError.new("File not found #{file_path}") unless File.file?(file_path)
|
14
|
+
hash_students = typer.read_file(File.read(file_path))
|
15
|
+
self.students = hash_students.map{|h| Student.from_hash(h)}
|
16
|
+
nextId
|
17
|
+
end
|
18
|
+
|
19
|
+
def write_file(file_path)
|
20
|
+
hash_students = students.map(&:to_hash)
|
21
|
+
File.write(file_path, typer.write_file(hash_students))
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_student(stud_id)
|
25
|
+
students.find{|s| s.id == stud_id}
|
26
|
+
end
|
27
|
+
|
28
|
+
def sorted
|
29
|
+
students.sort_by(&:fio)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_student(student)
|
33
|
+
students << student
|
34
|
+
student.id = gen_id
|
35
|
+
nextId
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_students_pag(k,n,existing_data = nil)
|
39
|
+
skip = (k-1) * n
|
40
|
+
new_data = students[skip, n].map{|s| StudentShort.from_student_class(s)}
|
41
|
+
|
42
|
+
return DataListStudentShort.new(new_data) if existing_data.nil?
|
43
|
+
|
44
|
+
existing_data.replace_objects(new_data)
|
45
|
+
existing_data
|
46
|
+
end
|
47
|
+
|
48
|
+
def replace_student(student_id, student)
|
49
|
+
idx = student.find{|s| s.id==student.id}
|
50
|
+
self.students[idx]=student
|
51
|
+
end
|
52
|
+
|
53
|
+
def remove_student(student_id)
|
54
|
+
self.students.reject! {|s| s.id==student_id}
|
55
|
+
end
|
56
|
+
|
57
|
+
def count
|
58
|
+
self.students.count
|
59
|
+
end
|
60
|
+
|
61
|
+
def nextId
|
62
|
+
self.gen_id=students.max_by(&:id).id + 1
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../Student_list'
|
3
|
+
class StudentsListAdapter
|
4
|
+
private_class_method :new
|
5
|
+
def get_student(id)
|
6
|
+
end
|
7
|
+
|
8
|
+
def remove_student(id)
|
9
|
+
end
|
10
|
+
|
11
|
+
def replace_student(id, student)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_students_pag(k, n, data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_student(student)
|
18
|
+
end
|
19
|
+
|
20
|
+
def count
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class StudentsListDBAdapter < StudentsListAdapter
|
25
|
+
private
|
26
|
+
attr_accessor :database_list
|
27
|
+
|
28
|
+
public_class_method :new
|
29
|
+
|
30
|
+
public
|
31
|
+
def initialize(database_list)
|
32
|
+
self.database_list = database_list
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_student(id)
|
36
|
+
database_list.get_student(id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def remove_student(id)
|
40
|
+
database_list.remove_student(id)
|
41
|
+
end
|
42
|
+
|
43
|
+
def replace_student(id, student)
|
44
|
+
database_list.replace_student(id, student)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_students_pag(from, to, data)
|
48
|
+
database_list.get_students_pag(from, to, data)
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_student(student)
|
52
|
+
database_list.add_student(student)
|
53
|
+
end
|
54
|
+
|
55
|
+
def count
|
56
|
+
database_list.count
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class StudentsListConverterAdapter < StudentsListAdapter
|
61
|
+
private
|
62
|
+
attr_accessor :file_list
|
63
|
+
|
64
|
+
public_class_method :new
|
65
|
+
|
66
|
+
public
|
67
|
+
def initialize(file_list, filename)
|
68
|
+
self.file_list = file_list
|
69
|
+
self.file_list.read_file(filename)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_student(id)
|
73
|
+
file_list.get_student(id)
|
74
|
+
end
|
75
|
+
|
76
|
+
def remove_student(id)
|
77
|
+
file_list.remove_student(id)
|
78
|
+
end
|
79
|
+
|
80
|
+
def replace_student(id, student)
|
81
|
+
file_list.replace_student(id, student)
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_students_pag(k, n, data=nil)
|
85
|
+
file_list.get_students_pag(k, n, data)
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_student(student)
|
89
|
+
file_list.add_student(student)
|
90
|
+
end
|
91
|
+
|
92
|
+
def count
|
93
|
+
file_list.count
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class DataList
|
2
|
+
private_class_method :new
|
3
|
+
|
4
|
+
attr_accessor :selected_num, :objects
|
5
|
+
|
6
|
+
def initialize(*elems)
|
7
|
+
self.objects = elems
|
8
|
+
@listeners = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_listener(listener)
|
12
|
+
@listeners << listener
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove_listener(listener)
|
16
|
+
@listeners.delete(listener)
|
17
|
+
end
|
18
|
+
|
19
|
+
def notify
|
20
|
+
@listeners.each { |lst| lst.on_datalist_changed(data_table) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def select_element(number)
|
24
|
+
self.selected_num = number < objects.size ? number : nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def selected_id
|
28
|
+
objects[selected_num].id
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_names
|
32
|
+
self.objects.first.instance_variables.map{|v| v.to_s[1..-1]}
|
33
|
+
end
|
34
|
+
|
35
|
+
def table_fields(_obj)
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
|
39
|
+
def data_table
|
40
|
+
result = []
|
41
|
+
counter = 0
|
42
|
+
objects.each do |obj|
|
43
|
+
row = []
|
44
|
+
row << counter
|
45
|
+
row.push(*table_fields(obj))
|
46
|
+
result << row
|
47
|
+
counter += 1
|
48
|
+
end
|
49
|
+
DataTable.new(result)
|
50
|
+
end
|
51
|
+
|
52
|
+
def append(new_data)
|
53
|
+
self.objects.append(new_data)
|
54
|
+
end
|
55
|
+
|
56
|
+
def replace_objects(objects)
|
57
|
+
self.objects = objects.dup
|
58
|
+
notify
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def instance_variables_wout_id(object)
|
63
|
+
object.instance_variables.reject{|v| v.to_sym ==:@id}.map{|v| object.instance_variable_get(v)}
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../model/Student_short'
|
2
|
+
require_relative '../containers/Data_table'
|
3
|
+
require_relative 'Data_list'
|
4
|
+
class DataListStudentShort < DataList
|
5
|
+
|
6
|
+
public_class_method :new
|
7
|
+
|
8
|
+
def get_names
|
9
|
+
['Фамилия И.О.','Гит','Контакт']
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def table_fields(obj)
|
14
|
+
[obj.fio, obj.git, obj.contact]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class DataTable
|
2
|
+
|
3
|
+
attr_accessor :data
|
4
|
+
|
5
|
+
def initialize(data)
|
6
|
+
self.data = data
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_cell(row,col)
|
10
|
+
self.data[row][col]
|
11
|
+
end
|
12
|
+
|
13
|
+
def num_columns
|
14
|
+
self.data[0].length
|
15
|
+
end
|
16
|
+
|
17
|
+
def num_rows
|
18
|
+
self.data.length
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_2d_array
|
22
|
+
data.dup
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'json'
|
2
|
+
require_relative '../converters/Converter'
|
3
|
+
class ConverterJSON < Converter
|
4
|
+
public_class_method :new
|
5
|
+
|
6
|
+
def read_file(file_content)
|
7
|
+
JSON.parse(file_content, {symbolize_names: true})
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_file(hash_students)
|
11
|
+
JSON.pretty_generate(hash_students)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative '../verter'
|
2
|
+
class ConverterTxt < Converter
|
3
|
+
public_class_method :new
|
4
|
+
|
5
|
+
def read_file(data)
|
6
|
+
result = []
|
7
|
+
file_content = data.split("\n")
|
8
|
+
file_content.each do |line|
|
9
|
+
hash = {}
|
10
|
+
puts(line)
|
11
|
+
pairs = line.split(',').map{|pair| pair.gsub(/\s+/, '').split(':')}
|
12
|
+
pairs.each do |pair|
|
13
|
+
hash[pair[0].to_sym]=(pair[0]=="id") ? pair[1].to_i : pair[1]
|
14
|
+
end
|
15
|
+
result << hash
|
16
|
+
end
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def write_file(hash_students)
|
21
|
+
string_arr = hash_students.map do |hash|
|
22
|
+
hash.map{|k,v| "#{k}:#{v}"}.join(',')
|
23
|
+
end.join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require_relative '../verter'
|
3
|
+
class ConverterYAML < Converter
|
4
|
+
public_class_method :new
|
5
|
+
|
6
|
+
def read_file(file_content)
|
7
|
+
YAML.safe_load(file_content).map{ |h| h.transform_keys(&:to_sym)}
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_file(hash_students)
|
11
|
+
YAML.dump(hash_students.map{ |h| h.transform_keys(&:to_s)})
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
CREATE TABLE IF NOT EXISTS student(
|
2
|
+
id INT NOT NULL auto_increment PRIMARY KEY,
|
3
|
+
last_name CHAR(255) NOT NULL,
|
4
|
+
first_name CHAR(255) NOT NULL,
|
5
|
+
parental_name CHAR(255) NOT NULL,
|
6
|
+
git CHAR(255),
|
7
|
+
phone CHAR(255),
|
8
|
+
email CHAR(255),
|
9
|
+
telegram CHAR(255)
|
10
|
+
);
|
@@ -0,0 +1,4 @@
|
|
1
|
+
INSERT INTO student (last_name, first_name, parental_name, git, phone, email, telegram) VALUES
|
2
|
+
ROW("Худокормов", "Дмитрий", "Александрович", "@KiTTeNqz", NULL, NULL, "@KiTTeNqzi"),
|
3
|
+
ROW("Александров", "Александр", "Александрович", "@AleXxx", "89094494499", NULL, NULL),
|
4
|
+
ROW("Ермаков", "Ермак", "Ермакович", "@yaErmak1", NULL, "ERMAK@yandex.ru", NULL)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative './students_db.rb'
|
3
|
+
|
4
|
+
class StudentListDB
|
5
|
+
attr_accessor :database
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance ||= StudentListDB.new
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
self.database = StudentDB.new()
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_student(id)
|
19
|
+
Student.from_hash(database.select_by_id(id).transform_keys(&:to_sym))
|
20
|
+
end
|
21
|
+
|
22
|
+
def remove_student(id)
|
23
|
+
database.remove_by_id(id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def replace_student(id, student)
|
27
|
+
database.replace_by_id(id, student)
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_student(student)
|
31
|
+
database.add_student(student.to_hash)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_students_pag(k, n, data)
|
35
|
+
database.get_students_pag(k, n, data)
|
36
|
+
end
|
37
|
+
|
38
|
+
def count
|
39
|
+
database.count
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# #encoding: UTF-8
|
3
|
+
require 'mysql2'
|
4
|
+
require_relative '../containers/Data_list_student_short'
|
5
|
+
require_relative '../containers/Data_list'
|
6
|
+
require_relative '../model/Student'
|
7
|
+
require_relative '../model/Student_short'
|
8
|
+
class StudentDB
|
9
|
+
|
10
|
+
attr_accessor :db_connection
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
self.db_connection = Mysql2::Client.new(:host => "localhost", :username => "dimas", :password => "qwe123")
|
14
|
+
self.db_connection.query('CREATE DATABASE IF NOT EXISTS stud_db')
|
15
|
+
self.db_connection.query('USE stud_db')
|
16
|
+
self.db_connection.query('DROP TABLE IF EXISTS student')
|
17
|
+
self.db_connection.query(File.read('C:/Users/Dmitry/RubymineProjects/RubyLabs/mvcStudentXD/lib/database/scripts/create_table.sql'))
|
18
|
+
self.insert_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def insert_data
|
22
|
+
db_connection.query(File.read('C:/Users/Dmitry/RubymineProjects/RubyLabs/mvcStudentXD/lib/database/scripts/insert_data.sql'))
|
23
|
+
end
|
24
|
+
|
25
|
+
def select_by_id(id)
|
26
|
+
db_connection.query("SELECT * FROM student WHERE id = #{id}").map{|x| x}[0]
|
27
|
+
end
|
28
|
+
|
29
|
+
def remove_by_id(id)
|
30
|
+
db_connection.query("DELETE FROM student WHERE id = #{id}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def parseNil(attr)
|
34
|
+
if attr == nil
|
35
|
+
"NULL"
|
36
|
+
else
|
37
|
+
attr
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_student(student_data)
|
42
|
+
|
43
|
+
db_connection.query("""
|
44
|
+
INSERT INTO student (last_name, first_name, parental_name, git, phone, email, telegram) VALUES
|
45
|
+
ROW(
|
46
|
+
\"#{parseNil(student_data[:last_name])}\",
|
47
|
+
\"#{parseNil(student_data[:first_name])}\",
|
48
|
+
\"#{parseNil(student_data[:parental_name])}\",
|
49
|
+
\"#{parseNil(student_data[:git])}\",
|
50
|
+
\"#{parseNil(student_data[:phone])}\",
|
51
|
+
\"#{parseNil(student_data[:email])}\",
|
52
|
+
\"#{parseNil(student_data[:telegram])}\"
|
53
|
+
)
|
54
|
+
""")
|
55
|
+
end
|
56
|
+
|
57
|
+
def replace_by_id(id, student_data)
|
58
|
+
self.remove_by_id(id)
|
59
|
+
self.add_student(student_data.to_hash)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_students_pag(k, n, existing_data = nil)
|
63
|
+
rows = db_connection.query("SELECT * FROM student ORDER BY id LIMIT #{n} OFFSET #{(k-1)*n}")
|
64
|
+
data_list = DataListStudentShort.new
|
65
|
+
rows.each do |row|
|
66
|
+
row_sym = row.transform_keys{|key| key.to_sym}
|
67
|
+
data_list.append(StudentShort.from_student_class(Student.from_hash(row_sym)))
|
68
|
+
end
|
69
|
+
return data_list if existing_data.nil?
|
70
|
+
existing_data.replace_objects(data_list.objects)
|
71
|
+
existing_data
|
72
|
+
end
|
73
|
+
|
74
|
+
def count
|
75
|
+
result = db_connection.query("SELECT count(*) FROM student")
|
76
|
+
result.first.values.first
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'json'
|
2
|
+
require_relative '../model/StudentBase'
|
3
|
+
class Student < StudentBase
|
4
|
+
|
5
|
+
public_class_method :new
|
6
|
+
attr_writer :id
|
7
|
+
public
|
8
|
+
attr_reader :last_name, :first_name, :parental_name, :id, :phone, :git, :telegram, :email
|
9
|
+
|
10
|
+
def initialize(last_name, first_name, parental_name, options = {})
|
11
|
+
super(last_name, first_name, parental_name)
|
12
|
+
self.id = options[:id]
|
13
|
+
self.phone = options[:phone]
|
14
|
+
self.git = options[:git]
|
15
|
+
self.telegram = options[:telegram]
|
16
|
+
self.email = options[:email]
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
[
|
21
|
+
"#{last_name} #{first_name} #{parental_name}",
|
22
|
+
id ? "id: #{id}" : nil,
|
23
|
+
git ? "git: #{git}" : nil,
|
24
|
+
phone ? "phone: #{phone}" : nil,
|
25
|
+
telegram ? "telegram: #{telegram}" : nil,
|
26
|
+
email ? "email: #{email}" : nil
|
27
|
+
].compact.join(' ')
|
28
|
+
end
|
29
|
+
|
30
|
+
#Setters
|
31
|
+
def phone=(phone)
|
32
|
+
raise ArgumentError, "ERROR phone=#{phone}" unless phone.nil? || StudentBase.validate_phone?(phone)
|
33
|
+
@phone = phone
|
34
|
+
end
|
35
|
+
|
36
|
+
def telegram=(tg_name)
|
37
|
+
raise ArgumentError, "ERROR telegram=#{tg_name}" unless telegram.nil? || StudentBase.validate_git_tg?(tg_name)
|
38
|
+
@telegram=tg_name
|
39
|
+
end
|
40
|
+
|
41
|
+
def git=(git_name)
|
42
|
+
raise ArgumentError, "ERROR git=#{git_name}" unless git.nil? || StudentBase.validate_git_tg?(git_name)
|
43
|
+
@git=git_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def email=(email1)
|
47
|
+
raise ArgumentError, "ERROR email=#{email1}" unless email.nil? || StudentBase.validate_email?(email1)
|
48
|
+
@email=email1
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_contacts(contacts={})
|
52
|
+
self.phone=contacts[:phone]
|
53
|
+
self.telegram=contacts[:telegram]
|
54
|
+
self.email=contacts[:email]
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.from_str(string)
|
58
|
+
stud = string.split(',')
|
59
|
+
.map{|v| v.split(':')}
|
60
|
+
.map{|v| [v[0].to_sym, v[1]]}
|
61
|
+
.to_h
|
62
|
+
last_name, first_name, parental_name = stud[:fio].split(' ')
|
63
|
+
Student.new(last_name, first_name, parental_name, stud)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.from_hash(hash)
|
67
|
+
raise ArgumentError,"Missing req fields" unless hash.key?(:last_name) && hash.key?(:first_name) && hash.key?(:parental_name)
|
68
|
+
#переделал этот метод после тестов. Теперь вынимаю обязательные параметры из хэша, не удаляя из него
|
69
|
+
Student.new(hash[:last_name], hash[:first_name], hash[:parental_name], hash)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_short_fio
|
73
|
+
"fio:#{last_name} #{first_name[0]}. #{parental_name[0]}."
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def get_short_contact
|
78
|
+
contact = %i[telegram phone email].find{|cont| send(cont)}
|
79
|
+
{type: contact, val: send(contact)} if contact
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_git
|
83
|
+
"git:#{git}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_info
|
87
|
+
"#{get_short_fio},#{get_short_contact[:type]}:#{get_short_contact[:val]},#{get_git}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_info_hash
|
91
|
+
info={}
|
92
|
+
info[:fio] = get_short_fio
|
93
|
+
info[:contact] = get_short_contact
|
94
|
+
info[:git] = git
|
95
|
+
info
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_hash
|
99
|
+
fields = {}
|
100
|
+
%i[last_name first_name parental_name id phone git telegram email].each do |field|
|
101
|
+
field_val = send(field)
|
102
|
+
fields[field] = field_val unless field_val.nil?
|
103
|
+
end
|
104
|
+
fields
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'json'
|
2
|
+
class StudentBase
|
3
|
+
private_class_method :new
|
4
|
+
|
5
|
+
def self.validate_phone?(phone)
|
6
|
+
return phone.match(/^\+?[7,8] ?\(?\d{3}\)? ?\d{3}-?\d{2}-?\d{2}$/)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.validate_email?(email)
|
10
|
+
return email.match(/^[A-Za-z0-9\-_]+@[A-Za-z]+(\.[A-Za-z]+)?\.[A-Za-z]+$/)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.validate_git_tg?(acc_name)
|
14
|
+
return acc_name.match(/^@[A-Za-z0-9\-_]+$/)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.validate_name?(prof_name)
|
18
|
+
return prof_name.match(/(^[А-Я][а-я]+$)|(^[A-Z][a-z]+$)/)
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid_cont?
|
22
|
+
!email.nil? || !telegram.nil? || !phone.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate?
|
26
|
+
!git.nil? && valid_cont?
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(last_name, first_name, parental_name)
|
30
|
+
self.last_name = last_name
|
31
|
+
self.first_name = first_name
|
32
|
+
self.parental_name = parental_name
|
33
|
+
end
|
34
|
+
|
35
|
+
def first_name=(first_name1)
|
36
|
+
raise ArgumentError, "ERROR first_name=#{first_name1}" unless StudentBase.validate_name?(first_name1)
|
37
|
+
@first_name=first_name1
|
38
|
+
end
|
39
|
+
|
40
|
+
def last_name=(last_name1)
|
41
|
+
raise ArgumentError, "ERROR last_name=#{last_name1}" unless StudentBase.validate_name?(last_name1)
|
42
|
+
@last_name=last_name1
|
43
|
+
end
|
44
|
+
|
45
|
+
def parental_name=(parental_name1)
|
46
|
+
raise ArgumentError, "ERROR parental_name=#{parental_name1}" unless StudentBase.validate_name?(parental_name1)
|
47
|
+
@parental_name=parental_name1
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../model/StudentBase'
|
2
|
+
class StudentShort < StudentBase
|
3
|
+
|
4
|
+
public_class_method :new
|
5
|
+
|
6
|
+
#У нас уже есть некоторые гет\сет в базе, зачем же ещё?
|
7
|
+
private
|
8
|
+
attr_writer :fio, :contact, :git, :id
|
9
|
+
|
10
|
+
public
|
11
|
+
attr_reader :fio, :contact, :git, :id
|
12
|
+
|
13
|
+
def self.from_student_class(student)
|
14
|
+
StudentShort.new(student.id, student.get_info)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(id, str)
|
18
|
+
info_short = str.split(',')
|
19
|
+
.map{|x| x.split(':')}
|
20
|
+
.map{|x| [x[0].to_sym, x[1]]}
|
21
|
+
.to_h
|
22
|
+
raise ArgumentError, 'Missing fields: fio' if info_short[:fio].nil?
|
23
|
+
print(info_short)
|
24
|
+
self.id=id
|
25
|
+
self.fio = info_short[:fio]
|
26
|
+
self.git = info_short[:git]
|
27
|
+
info_short.delete_if{|k,v| k==:fio||k==:git}
|
28
|
+
self.contact = info_short.values.first
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
|
34
|
+
[
|
35
|
+
"#{id}, #{fio}, #{git}, #{contact}"
|
36
|
+
].compact.join(' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/mvcStudentXD/version.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../../mvcStudentXD/lib/util/LoggerHolder'
|
3
|
+
class StudentEditFormController
|
4
|
+
def initialize(parent_controller, existing_student_id)
|
5
|
+
@parent_controller = parent_controller
|
6
|
+
@existing_student_id = existing_student_id
|
7
|
+
LoggerHolder.instance.debug('StudentEditFormController: initialized')
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_view(view)
|
11
|
+
@view = view
|
12
|
+
end
|
13
|
+
|
14
|
+
def refresh
|
15
|
+
@parent_controller.refresh_data(1,20)
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_view_created
|
19
|
+
begin
|
20
|
+
@student_list = StudentListAdv.new(StudentsListDBAdapter.new(StudentListDB.instance))
|
21
|
+
rescue Mysql2::Error::ConnectionError=>e
|
22
|
+
on_db_conn_error(e)
|
23
|
+
end
|
24
|
+
@existing_student = @student_list.get_student(@existing_student_id)
|
25
|
+
|
26
|
+
@view.make_readonly(:git, :telegram, :email, :phone)
|
27
|
+
populate_fields(@existing_student)
|
28
|
+
end
|
29
|
+
|
30
|
+
def populate_fields(student)
|
31
|
+
@view.set_value(:last_name, student.last_name)
|
32
|
+
@view.set_value(:first_name, student.first_name)
|
33
|
+
@view.set_value(:parental_name, student.parental_name)
|
34
|
+
@view.set_value(:git, student.git)
|
35
|
+
@view.set_value(:telegram, student.telegram)
|
36
|
+
@view.set_value(:email, student.email)
|
37
|
+
@view.set_value(:phone, student.phone)
|
38
|
+
print("IM IN Populate EDIT")
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_fields(fields)
|
42
|
+
begin
|
43
|
+
new_student = Student.from_hash(fields)
|
44
|
+
@student_list.replace_student(@existing_student_id, new_student)
|
45
|
+
LoggerHolder.instance.debug('StudentEditFormController: replacing student in DB')
|
46
|
+
@view.close
|
47
|
+
rescue ArgumentError => e
|
48
|
+
LoggerHolder.instance.debug("StudentEditFormController: wrong fields: #{e.message}")
|
49
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
50
|
+
api.call(0, e.message, 'Error', 0)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def on_db_conn_error(error)
|
57
|
+
LoggerHolder.instance.debug('StudentEditFormController: DB connection error:')
|
58
|
+
LoggerHolder.instance.error(error.message)
|
59
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
60
|
+
api.call(0, "No connection to DB", "Error", 0)
|
61
|
+
@view.close
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require_relative 'student_input_form_controller'
|
5
|
+
require_relative 'model/StudentBase'
|
6
|
+
require 'win32api'
|
7
|
+
|
8
|
+
class StudentInputForm
|
9
|
+
include Glimmer
|
10
|
+
|
11
|
+
def initialize(controller,existing_student = nil)
|
12
|
+
@existing_student = existing_student.to_hash unless existing_student.nil?
|
13
|
+
@controller = controller
|
14
|
+
@entries = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_create
|
18
|
+
@controller.on_view_created
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@root_container = window('Универ', 300, 150) {
|
23
|
+
resizable false
|
24
|
+
|
25
|
+
vertical_box {
|
26
|
+
@student_form = form {
|
27
|
+
stretchy false
|
28
|
+
|
29
|
+
fields = [[:last_name, 'Фамилия', false], [:first_name, 'Имя', false], [:parental_name, 'Отчество', false], [:git, 'Гит', true], [:telegram, 'Телеграм', true], [:email, 'Почта', true], [:phone, 'Телефон', true]]
|
30
|
+
|
31
|
+
fields.each do |field|
|
32
|
+
@entries[field[0]] = entry {
|
33
|
+
label field[1]
|
34
|
+
text @existing_student[field[0]] unless @existing_student.nil?
|
35
|
+
|
36
|
+
read_only field[2] unless @existing_student.nil?
|
37
|
+
}
|
38
|
+
end
|
39
|
+
}
|
40
|
+
|
41
|
+
button('Сохранить') {
|
42
|
+
stretchy false
|
43
|
+
|
44
|
+
on_clicked {
|
45
|
+
values = @entries.transform_values { |v| v.text.force_encoding("utf-8").strip }
|
46
|
+
values.transform_values! { |v| v.empty? ? nil : v}
|
47
|
+
@controller.process_fields(values)
|
48
|
+
@controller.refresh
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
on_create
|
54
|
+
@root_container
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_value(field, value)
|
58
|
+
return unless @entries.include?(field)
|
59
|
+
@entries[field].text = value
|
60
|
+
end
|
61
|
+
|
62
|
+
def make_readonly(*fields)
|
63
|
+
fields.each do |field|
|
64
|
+
@entries[field].read_only = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def close
|
69
|
+
@root_container.destroy
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'win32api'
|
4
|
+
require_relative '../../mvcStudentXD/lib/util/LoggerHolder'
|
5
|
+
class StudentInputFormController
|
6
|
+
def initialize(parent_controller)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
LoggerHolder.instance.debug('StudentInputFormController: initialized')
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_view(view)
|
12
|
+
@view = view
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def refresh
|
17
|
+
@parent_controller.refresh_data(1,20)
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_view_created
|
21
|
+
begin
|
22
|
+
@student_list = StudentListAdv.new(StudentsListDBAdapter.new(StudentListDB.instance))
|
23
|
+
rescue Mysql2::Error::ConnectionError=>e
|
24
|
+
on_db_conn_error(e)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_fields(fields)
|
29
|
+
begin
|
30
|
+
last_name = fields.delete(:last_name)
|
31
|
+
first_name = fields.delete(:first_name)
|
32
|
+
parental_name = fields.delete(:parental_name)
|
33
|
+
|
34
|
+
return if last_name.nil? || first_name.nil? || parental_name.nil?
|
35
|
+
|
36
|
+
student = Student.new(last_name, first_name, parental_name, **fields)
|
37
|
+
|
38
|
+
@student_list.add_student(student)
|
39
|
+
LoggerHolder.instance.debug('StudentInputFormController: adding student to DB')
|
40
|
+
@view.close
|
41
|
+
rescue ArgumentError => e
|
42
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
43
|
+
LoggerHolder.instance.debug("StudentInputFormController: wrong fields: #{e.message}")
|
44
|
+
api.call(0, e.message, 'Error', 0)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def on_db_conn_error(error)
|
50
|
+
LoggerHolder.instance.debug('StudentInputFormController: DB connection error:')
|
51
|
+
LoggerHolder.instance.error(error.message)
|
52
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
53
|
+
api.call(0, "No connection to DB", "Error", 0)
|
54
|
+
@view.close
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class StudentListAdv
|
4
|
+
private
|
5
|
+
attr_accessor :students_list_adapter
|
6
|
+
public
|
7
|
+
def initialize(students_list_adapter)
|
8
|
+
self.students_list_adapter = students_list_adapter
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_student(id)
|
12
|
+
students_list_adapter.get_student(id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove_student(id)
|
16
|
+
students_list_adapter.remove_student(id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def replace_student(id, student)
|
20
|
+
students_list_adapter.replace_student(id, student)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_students_pag(k, n, data)
|
24
|
+
students_list_adapter.get_students_pag(k, n, data)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_student(student)
|
28
|
+
students_list_adapter.add_student(student)
|
29
|
+
end
|
30
|
+
|
31
|
+
def count
|
32
|
+
students_list_adapter.count
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
require_relative 'student_list_adv'
|
5
|
+
require_relative 'adapters/student_list_adapter'
|
6
|
+
require_relative 'database/student_list_db'
|
7
|
+
require_relative 'converters/Converter_json'
|
8
|
+
require_relative 'converters/Converter'
|
9
|
+
require_relative 'Student_list'
|
10
|
+
require_relative 'student_edit_form_controller'
|
11
|
+
require 'win32api'
|
12
|
+
require 'mysql2'
|
13
|
+
require_relative '../../mvcStudentXD/lib/util/LoggerHolder'
|
14
|
+
class StudentListController
|
15
|
+
def initialize(view)
|
16
|
+
LoggerHolder.instance.debug('StudentListController: init start')
|
17
|
+
@view = view
|
18
|
+
@data_list = DataListStudentShort.new
|
19
|
+
@data_list.add_listener(@view)
|
20
|
+
LoggerHolder.instance.debug('StudentListController: init done')
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_view_created
|
24
|
+
begin
|
25
|
+
@student_list = StudentListAdv.new(StudentsListDBAdapter.new(StudentListDB.instance))
|
26
|
+
LoggerHolder.instance.debug('StudentListController: created student repository')
|
27
|
+
rescue Mysql2::Error::ConnectionError=>e
|
28
|
+
on_db_conn_error(e)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_selected(current_page, per_page, selected_row)
|
33
|
+
begin
|
34
|
+
LoggerHolder.instance.debug('StudentListController: deleting selected student')
|
35
|
+
student_num = (current_page - 1) * per_page + selected_row
|
36
|
+
@data_list.select_element(student_num)
|
37
|
+
student_id = @data_list.selected_id
|
38
|
+
@student_list.remove_student(student_id)
|
39
|
+
rescue => e
|
40
|
+
on_db_conn_error(e)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def show_modal_add
|
45
|
+
LoggerHolder.instance.debug('StudentListController: showing modal (add)')
|
46
|
+
controller = StudentInputFormController.new(self)
|
47
|
+
view = StudentInputForm.new(controller)
|
48
|
+
controller.set_view(view)
|
49
|
+
view.create.show
|
50
|
+
end
|
51
|
+
|
52
|
+
def show_modal_edit(current_page, per_page, selected_row)
|
53
|
+
LoggerHolder.instance.debug('StudentListController: 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 = StudentEditFormController.new(self, student_id)
|
58
|
+
view = StudentInputForm.new(controller)
|
59
|
+
controller.set_view(view)
|
60
|
+
view.create.show
|
61
|
+
end
|
62
|
+
|
63
|
+
def refresh_data(page, per_page)
|
64
|
+
begin
|
65
|
+
@data_list = @student_list.get_students_pag(page, per_page, @data_list)
|
66
|
+
@view.update_student_count(@student_list.count)
|
67
|
+
rescue => e
|
68
|
+
on_db_conn_error(e)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def on_db_conn_error(error)
|
74
|
+
LoggerHolder.instance.error('TabStudentsController: DB connection error:')
|
75
|
+
LoggerHolder.instance.error(error.message)
|
76
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
77
|
+
api.call(0, "No connection to DB", "Error", 0)
|
78
|
+
# TODO: Возможность переключения на JSON помимо exit
|
79
|
+
exit(false)
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/mvcStudentXD/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "mvcStudentXD"
|
7
|
+
spec.version = MvcStudentXD::VERSION
|
8
|
+
spec.authors = ["papaSquid"]
|
9
|
+
spec.email = ["mrxameleonx@mail.ru"]
|
10
|
+
spec.license = "MIT"
|
11
|
+
spec.summary = "Gem with Student MC"
|
12
|
+
spec.description = "models and controllers"
|
13
|
+
spec.homepage = "https://github.com/KiTTeNqz/mvcStudentXD"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/KiTTeNqz/mvcStudentXD"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/KiTTeNqz/mvcStudentXD/blob/master/CHANGELOG.md"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(__dir__) do
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
# Uncomment to register a new dependency of your gem
|
34
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
35
|
+
|
36
|
+
# For more information and examples about making a new gem, check out our
|
37
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
38
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mvcStudentXD
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- papaSquid
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: models and controllers
|
14
14
|
email:
|
@@ -23,8 +23,30 @@ files:
|
|
23
23
|
- Gemfile
|
24
24
|
- README.md
|
25
25
|
- Rakefile
|
26
|
+
- lib/Student_list.rb
|
27
|
+
- lib/adapters/student_list_adapter.rb
|
28
|
+
- lib/containers/Data_list.rb
|
29
|
+
- lib/containers/Data_list_student_short.rb
|
30
|
+
- lib/containers/Data_table.rb
|
31
|
+
- lib/converters/Converter.rb
|
32
|
+
- lib/converters/Converter_json.rb
|
33
|
+
- lib/converters/Converter_txt.rb
|
34
|
+
- lib/converters/Converter_yaml.rb
|
35
|
+
- lib/database/scripts/create_table.sql
|
36
|
+
- lib/database/scripts/insert_data.sql
|
37
|
+
- lib/database/student_list_db.rb
|
38
|
+
- lib/database/students_db.rb
|
39
|
+
- lib/model/Student.rb
|
40
|
+
- lib/model/StudentBase.rb
|
41
|
+
- lib/model/Student_short.rb
|
26
42
|
- lib/mvcStudentXD.rb
|
27
43
|
- lib/mvcStudentXD/version.rb
|
44
|
+
- lib/student_edit_form_controller.rb
|
45
|
+
- lib/student_input_form.rb
|
46
|
+
- lib/student_input_form_controller.rb
|
47
|
+
- lib/student_list_adv.rb
|
48
|
+
- lib/student_list_controller.rb
|
49
|
+
- mvcStudentXD.gemspec
|
28
50
|
- sig/mvcStudentXD.rbs
|
29
51
|
homepage: https://github.com/KiTTeNqz/mvcStudentXD
|
30
52
|
licenses:
|