rubbish_code 0.1.1 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +84 -0
  4. data/Documentation.md +33 -0
  5. data/Gemfile +13 -0
  6. data/LICENSE.txt +15 -31
  7. data/lib/rubbish_code/version.rb +5 -0
  8. data/lib/rubbish_code.rb +10 -0
  9. data/lib/{controllers → source/controllers}/student_input_form/student_input_form_controller_create.rb +15 -4
  10. data/lib/{controllers → source/controllers}/student_input_form/student_input_form_controller_edit.rb +16 -4
  11. data/lib/{controllers → source/controllers}/tab_students_controller.rb +27 -20
  12. data/lib/source/db_config/config.yaml +5 -0
  13. data/lib/source/db_config/migrations/001_create_table_student.sql +12 -0
  14. data/lib/source/db_config/mock_data/fill_student.sql +5 -0
  15. data/lib/source/models/student_test.rb +71 -0
  16. data/lib/source/repositories/adapters/db_source_adapter.rb +54 -0
  17. data/lib/source/repositories/adapters/file_source_adapter.rb +37 -0
  18. data/lib/source/repositories/containers/data_list.rb +74 -0
  19. data/lib/source/repositories/containers/data_list_student_short.rb +18 -0
  20. data/lib/source/repositories/containers/data_table.rb +35 -0
  21. data/lib/source/repositories/data_sources/db_data_source.rb +36 -0
  22. data/lib/source/repositories/data_sources/file_data_source.rb +75 -0
  23. data/lib/source/repositories/data_sources/transformers/data_transformer_base.rb +15 -0
  24. data/lib/source/repositories/data_sources/transformers/data_transformer_json.rb +16 -0
  25. data/lib/source/repositories/data_sources/transformers/data_transformer_yaml.rb +16 -0
  26. data/lib/source/repositories/student_repository.rb +32 -0
  27. data/lib/source/util/logger_holder.rb +24 -0
  28. data/rubbish_code.gemspec +17 -0
  29. data/sig/ribbish_code.rbs +4 -0
  30. metadata +35 -10
  31. /data/lib/{models → source/models}/student.rb +0 -0
  32. /data/lib/{models → source/models}/student_base.rb +0 -0
  33. /data/lib/{models → source/models}/student_short.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d740f9c6240c70d88d6c8871c16c2d741f84d68195082042e5a7c35251904f56
4
- data.tar.gz: bf470d916acc2f7c9492ef2d0c635c8a521ed474b203dd41f855ec5c508bca71
3
+ metadata.gz: 704e3897e8f44aebbccd201679e9ecf8188969a0fa0e2e9df5e025dce7bf8cd5
4
+ data.tar.gz: 6fd1c258b63ba5079253bb0849f8ad66d689008691ac2a0b9da690abb51c95b5
5
5
  SHA512:
6
- metadata.gz: b3de6e75f75aedbba00944a4e0260a9646f06487ee8225b57b74d0701288243c20ab2b36541024ed978486f8f02ce8ebc67f858aea38faf411fe3f5e841142ee
7
- data.tar.gz: bbba813b161d589bbde9ef024e63820c04cd7fa8bc36ca317acd54221d26bd3721163be032d3ed9b3fbd0cc73c5c5160c5142feab1da44c63a3d58d16382c092
6
+ metadata.gz: 7c4dbf4065b011aaf46803956e843295f675e6851c2f834417effaf0dd244a6b4cf3045cecb6d27d0bbbd2d632710d676f186c2fe3227ac359e581dfb8c8ba24
7
+ data.tar.gz: 953b81ec8a65ff9d03fab491b798975a1749a10fbc3b988ab13e893b1d4c7d8d0cfac1ce6bc4405762de19b767d49eea544764afb629367049ec2bddc390e13a
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-04-28
4
+
5
+ - Initial release
@@ -0,0 +1,84 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment for our community include:
12
+
13
+ * Demonstrating empathy and kindness toward other people
14
+ * Being respectful of differing opinions, viewpoints, and experiences
15
+ * Giving and gracefully accepting constructive feedback
16
+ * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ * Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior include:
20
+
21
+ * The use of sexualized language or imagery, and sexual attention or
22
+ advances of any kind
23
+ * Trolling, insulting or derogatory comments, and personal or political attacks
24
+ * Public or private harassment
25
+ * Publishing others' private information, such as a physical or email
26
+ address, without their explicit permission
27
+ * Other conduct which could reasonably be considered inappropriate in a
28
+ professional setting
29
+
30
+ ## Enforcement Responsibilities
31
+
32
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
33
+
34
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
35
+
36
+ ## Scope
37
+
38
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
39
+
40
+ ## Enforcement
41
+
42
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at delta.null@vk.com. All complaints will be reviewed and investigated promptly and fairly.
43
+
44
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
45
+
46
+ ## Enforcement Guidelines
47
+
48
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
49
+
50
+ ### 1. Correction
51
+
52
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
53
+
54
+ **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
55
+
56
+ ### 2. Warning
57
+
58
+ **Community Impact**: A violation through a single incident or series of actions.
59
+
60
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
61
+
62
+ ### 3. Temporary Ban
63
+
64
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
65
+
66
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
67
+
68
+ ### 4. Permanent Ban
69
+
70
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
71
+
72
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
73
+
74
+ ## Attribution
75
+
76
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
77
+ available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
78
+
79
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
80
+
81
+ [homepage]: https://www.contributor-covenant.org
82
+
83
+ For answers to common questions about this code of conduct, see the FAQ at
84
+ https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
data/Documentation.md ADDED
@@ -0,0 +1,33 @@
1
+ The TabStudentsController class is a controller for working with the interface for interacting with objects of the Student type.
2
+
3
+ Methods of the class:
4
+
5
+ 1. initialize(view) - constructor of the class, takes a view object and creates an empty object of the type
6
+ DataListStudentShort, which is assigned the add_listener method with the view argument, as a result of which the view
7
+ is set as a listener for data state change events (data_list).
8
+ 2. on_view_created is a method that initializes an object of the StudentRepository type, which is used for interaction
9
+ with the database, and if an error occurs connecting to the database displays a dialog box with an error message.
10
+ 3. show_view is a method that displays the main application window.
11
+ 4. show_modal_add is a method that displays a modal window for creating a new student record.
12
+ Creates an instance of the StudentInputFormControllerCreate controller and passes it a reference to the current controller,
13
+ creates an object of the StudentInputForm type and passes it a reference to the controller. Then it displays the modal window.
14
+ 5. show_modal_edit(current_page, per_page, selected_row) is a method that displays the modal window for
15
+ editing a student record. Takes the values of the current page (current_page), the number of records on the page
16
+ (per_page) and the selected row (selected_row). Calculates the number of the selected student and selects his id from
17
+ the DataListStudentShort object, then passes it to the StudentInputFormControllerEdit controller, creates an object of the type
18
+ StudentInputForm and passes it a link to the controller. After that, it displays a modal window.
19
+ 6. delete_selected(current_page, per_page, selected_row) is a method that deletes the selected student record.
20
+ Takes the values of the current page (current_page), the number of records on the page (per_page)
21
+ and the selected row (selected_row). Calculates the number of the selected student and selects his id from the DataListStudentShort object,
22
+ then deletes the record using the remove_student method from the StudentRepository object.
23
+ 7. refresh_data(page, per_page) is a method that updates the data in the list of students. Takes the values
24
+ of the current page (page) and the number of entries on the page (per_page).
25
+ Calls a method of the StudentRepository paginated_short_students type to get data in the DataListStudentShort object format.
26
+ Updates information about the number of students using the update_student_count method of the view.
27
+
28
+ The Student_Input_Form_Controller_Edit controller and Student_Input_Form_Controller_Create are forms
29
+ for modifying and creating students into the database, respectively.
30
+
31
+ The student, student_base and student_short models are a student model with various fields and methods
32
+ for setting, receiving and processing information. Student_base - super class,
33
+ and student_short is the short information about the student.
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mysql2"
6
+ gem "glimmer-dsl-libui",'~> 0.7.4'
7
+ gem 'win32api'
8
+ gem "minitest"
9
+ gem 'rubocop', group: 'development'
10
+ gem 'rubbish_code', '~> 0.1.3'
11
+ gem 'sinatra', '~> 3.0', '>= 3.0.6'
12
+ gem 'thin', '~> 1.8', '>= 1.8.2'
13
+ gem 'mc_delta'
data/LICENSE.txt CHANGED
@@ -2,36 +2,20 @@ MIT License
2
2
 
3
3
  Copyright (c) 2023 NullExp
4
4
 
5
- The TabStudentsController class is a controller for working with the interface for interacting with objects of the Student type.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
6
11
 
7
- Methods of the class:
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
8
14
 
9
- 1. initialize(view) - constructor of the class, takes a view object and creates an empty object of the type
10
- DataListStudentShort, which is assigned the add_listener method with the view argument, as a result of which the view
11
- is set as a listener for data state change events (data_list).
12
- 2. on_view_created is a method that initializes an object of the StudentRepository type, which is used for interaction
13
- with the database, and if an error occurs connecting to the database displays a dialog box with an error message.
14
- 3. show_view is a method that displays the main application window.
15
- 4. show_modal_add is a method that displays a modal window for creating a new student record.
16
- Creates an instance of the StudentInputFormControllerCreate controller and passes it a reference to the current controller,
17
- creates an object of the StudentInputForm type and passes it a reference to the controller. Then it displays the modal window.
18
- 5. show_modal_edit(current_page, per_page, selected_row) is a method that displays the modal window for
19
- editing a student record. Takes the values of the current page (current_page), the number of records on the page
20
- (per_page) and the selected row (selected_row). Calculates the number of the selected student and selects his id from
21
- the DataListStudentShort object, then passes it to the StudentInputFormControllerEdit controller, creates an object of the type
22
- StudentInputForm and passes it a link to the controller. After that, it displays a modal window.
23
- 6. delete_selected(current_page, per_page, selected_row) is a method that deletes the selected student record.
24
- Takes the values of the current page (current_page), the number of records on the page (per_page)
25
- and the selected row (selected_row). Calculates the number of the selected student and selects his id from the DataListStudentShort object,
26
- then deletes the record using the remove_student method from the StudentRepository object.
27
- 7. refresh_data(page, per_page) is a method that updates the data in the list of students. Takes the values
28
- of the current page (page) and the number of entries on the page (per_page).
29
- Calls a method of the StudentRepository paginated_short_students type to get data in the DataListStudentShort object format.
30
- Updates information about the number of students using the update_student_count method of the view.
31
-
32
- The Student_Input_Form_Controller_Edit controller and Student_Input_Form_Controller_Create are forms
33
- for modifying and creating students into the database, respectively.
34
-
35
- The student, student_base and student_short models are a student model with various fields and methods
36
- for setting, receiving and processing information. Student_base - super class,
37
- and student_short is the short information about the student.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubbishCode
4
+ VERSION = "0.1.4"
5
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rubbish_code/version"
4
+
5
+ module RubbishCode
6
+ Dir[File.dirname(__FILE__) + '/source/**/*.rb'].each { |file|
7
+ puts file
8
+ require file
9
+ }
10
+ end
@@ -1,21 +1,27 @@
1
1
  # frozen_string_literal: true
2
-
2
+ require './LabStudents/util/logger_holder'
3
3
  require 'win32api'
4
4
 
5
5
  class StudentInputFormControllerCreate
6
6
  def initialize(parent_controller)
7
7
  @parent_controller = parent_controller
8
+ LoggerHolder.instance.debug('StudentInputFormControllerCreate: initialized')
8
9
  end
9
10
 
10
11
  def set_view(view)
11
12
  @view = view
13
+ LoggerHolder.instance.debug('StudentInputFormControllerCreate: view set')
14
+ end
15
+
16
+ def refresh
17
+ @parent_controller.refresh_data(1, 20)
12
18
  end
13
19
 
14
20
  def on_view_created
15
21
  begin
16
22
  @student_rep = StudentRepository.new(DBSourceAdapter.new)
17
- rescue Mysql2::Error::ConnectionError
18
- on_db_conn_error
23
+ rescue Mysql2::Error::ConnectionError => e
24
+ on_db_conn_error(e)
19
25
  end
20
26
  end
21
27
 
@@ -31,8 +37,11 @@ class StudentInputFormControllerCreate
31
37
 
32
38
  @student_rep.add_student(student)
33
39
 
40
+ LoggerHolder.instance.debug('StudentInputFormControllerCreate: adding student to DB')
41
+
34
42
  @view.close
35
43
  rescue ArgumentError => e
44
+ LoggerHolder.instance.debug("StudentInputFormControllerCreate: wrong fields: #{e.message}")
36
45
  api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
37
46
  api.call(0, e.message, 'Error', 0)
38
47
  end
@@ -40,7 +49,9 @@ class StudentInputFormControllerCreate
40
49
 
41
50
  private
42
51
 
43
- def on_db_conn_error
52
+ def on_db_conn_error(error)
53
+ LoggerHolder.instance.debug('StudentInputFormControllerCreate: DB connection error:')
54
+ LoggerHolder.instance.error(error.message)
44
55
  api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
45
56
  api.call(0, "No connection to DB говно", "Error", 0)
46
57
  @view.close
@@ -1,25 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require './LabStudents/util/logger_holder'
3
4
  require 'win32api'
4
5
 
5
6
  class StudentInputFormControllerEdit
6
7
  def initialize(parent_controller, existing_student_id)
7
8
  @parent_controller = parent_controller
8
9
  @existing_student_id = existing_student_id
10
+ LoggerHolder.instance.debug('StudentInputFormControllerEdit: initialized')
9
11
  end
10
12
 
11
13
  def set_view(view)
12
14
  @view = view
15
+ LoggerHolder.instance.debug('StudentInputFormControllerEdit: view set')
16
+ end
17
+
18
+ def refresh
19
+ @parent_controller.refresh_data(1, 20)
13
20
  end
14
21
 
15
22
  def on_view_created
16
23
  begin
17
24
  @student_rep = StudentRepository.new(DBSourceAdapter.new)
18
- rescue Mysql2::Error::ConnectionError
19
- on_db_conn_error
25
+ rescue Mysql2::Error::ConnectionError => e
26
+ on_db_conn_error(e)
20
27
  end
21
28
  @existing_student = @student_rep.student_by_id(@existing_student_id)
22
- #@view.make_readonly(:git, :telegram, :email, :phone)
29
+ @view.make_readonly(:git, :telegram, :email, :phone)
23
30
  populate_fields(@existing_student)
24
31
  end
25
32
 
@@ -37,10 +44,13 @@ class StudentInputFormControllerEdit
37
44
  begin
38
45
  new_student = Student.from_hash(fields)
39
46
 
47
+ LoggerHolder.instance.debug('StudentInputFormControllerEdit: replacing student in DB')
48
+
40
49
  @student_rep.replace_student(@existing_student_id, new_student)
41
50
 
42
51
  @view.close
43
52
  rescue ArgumentError => e
53
+ LoggerHolder.instance.debug("StudentInputFormControllerEdit: wrong fields: #{e.message}")
44
54
  api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
45
55
  api.call(0, e.message, 'Error', 0)
46
56
  end
@@ -48,7 +58,9 @@ class StudentInputFormControllerEdit
48
58
 
49
59
  private
50
60
 
51
- def on_db_conn_error
61
+ def on_db_conn_error(error)
62
+ LoggerHolder.instance.debug('StudentInputFormControllerEdit: DB connection error:')
63
+ LoggerHolder.instance.error(error.message)
52
64
  api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
53
65
  api.call(0, "No connection to DB", "Error", 0)
54
66
  @view.close
@@ -7,28 +7,29 @@ require './LabStudents/repositories/containers/data_list_student_short'
7
7
  require './LabStudents/views/student_input_form'
8
8
  require './LabStudents/controllers/student_input_form/student_input_form_controller_create'
9
9
  require './LabStudents/controllers/student_input_form/student_input_form_controller_edit'
10
+ require './LabStudents/util/logger_holder'
10
11
  require 'win32api'
11
12
 
12
13
  class TabStudentsController
13
14
  def initialize(view)
15
+ LoggerHolder.instance.debug('TabStudentsController: init start')
14
16
  @view = view
15
17
  @data_list = DataListStudentShort.new([])
16
18
  @data_list.add_listener(@view)
19
+ LoggerHolder.instance.debug('TabStudentsController: init done')
17
20
  end
18
21
 
19
22
  def on_view_created
20
- #begin
23
+ begin
21
24
  @student_rep = StudentRepository.new(DBSourceAdapter.new)
22
- # rescue Mysql2::Error::ConnectionError
23
- # on_db_conn_error
24
- # end
25
- end
26
-
27
- def show_view
28
- @view.create.show
25
+ LoggerHolder.instance.debug('TabStudentsController: created student repository')
26
+ rescue Mysql2::Error::ConnectionError => e
27
+ on_db_conn_error(e)
28
+ end
29
29
  end
30
30
 
31
31
  def show_modal_add
32
+ LoggerHolder.instance.debug('TabStudentsController: showing modal (add)')
32
33
  controller = StudentInputFormControllerCreate.new(self)
33
34
  view = StudentInputForm.new(controller)
34
35
  controller.set_view(view)
@@ -36,6 +37,7 @@ class TabStudentsController
36
37
  end
37
38
 
38
39
  def show_modal_edit(current_page, per_page, selected_row)
40
+ LoggerHolder.instance.debug('TabStudentsController: showing modal (edit)')
39
41
  student_num = (current_page - 1) * per_page + selected_row
40
42
  @data_list.select_element(student_num)
41
43
  student_id = @data_list.selected_id
@@ -46,30 +48,35 @@ class TabStudentsController
46
48
  end
47
49
 
48
50
  def delete_selected(current_page, per_page, selected_row)
49
- #begin
51
+ begin
52
+ LoggerHolder.instance.debug('TabStudentsController: deleting selected student')
50
53
  student_num = (current_page - 1) * per_page + selected_row
51
54
  @data_list.select_element(student_num)
52
55
  student_id = @data_list.selected_id
53
56
  @student_rep.remove_student(student_id)
54
- # rescue
55
- # on_db_conn_error
56
- # end
57
+ rescue Mysql2::Error::ConnectionError => e
58
+ on_db_conn_error(e)
59
+ end
57
60
  end
58
61
 
59
62
  def refresh_data(page, per_page)
60
- #begin
63
+ begin
64
+ LoggerHolder.instance.debug('TabStudentsController: refreshing data...')
61
65
  @data_list = @student_rep.paginated_short_students(page, per_page, @data_list)
62
66
  @view.update_student_count(@student_rep.student_count)
63
- # rescue
64
- # on_db_conn_error
65
- # end
67
+ rescue Mysql2::Error::ConnectionError => e
68
+ on_db_conn_error(e)
69
+ end
66
70
  end
67
71
 
68
72
  private
69
73
 
70
- def on_db_conn_error
71
- # api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
72
- # api.call(0, "No connection to DB =)", "Error", 0)
73
- # exit(false)
74
+ def on_db_conn_error(error)
75
+ LoggerHolder.instance.error('TabStudentsController: DB connection error:')
76
+ LoggerHolder.instance.error(error.message)
77
+ api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
78
+ api.call(0, "No connection to DB", "Error", 0)
79
+ # TODO: Возможность переключения на JSON помимо exit
80
+ exit(false)
74
81
  end
75
82
  end
@@ -0,0 +1,5 @@
1
+ host: 'localhost'
2
+ port: 3306
3
+ username: 'root'
4
+ password: '1234'
5
+ database: 'university'
@@ -0,0 +1,12 @@
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
+ );
@@ -0,0 +1,5 @@
1
+ insert into student(last_name, first_name, father_name, phone, telegram, email, git) values
2
+ ('Хахук', 'Рустам', 'Нальбиевич', '79186733293', 'deltanull', 'deltanull@vk.ru', 'deltanull'),
3
+ ('Гиренко', 'Даниил', 'Егеньвич', NULL, 'gir', 'ashot@mail.ru', 'ashotgit'),
4
+ ('Гиренко', 'Даниил', 'Егеньвич', NULL, 'gir', 'ashot@mail.ru', 'ashotgit'),
5
+ ('Нагалевский', 'Артем', 'Великий', '79999999999', 'jakekepps', 'jakekepps@gmail.com', 'jakekepps');
@@ -0,0 +1,71 @@
1
+ require 'test/unit'
2
+ require_relative 'student'
3
+
4
+ class TestStudent < Test::Unit::TestCase
5
+ def setup
6
+ @student = Student.new('Иванов', 'Иван', 'Иванович')
7
+ end
8
+
9
+ def test_full_name
10
+ assert_equal('Иванов Иван Иванович', @student.to_s.split(', ')[0])
11
+ end
12
+
13
+ def test_contacts
14
+ @student = Student.new('Иванов', 'Иван', 'Иванович')
15
+ @student.set_contacts(phone: '+79991234567', email: 'ivanov@example.com')
16
+ assert_equal('+79991234567', @student.phone)
17
+ assert_equal('ivanov@example.com', @student.email)
18
+ end
19
+
20
+ def test_valid_name
21
+ assert(Student.valid_name?('Иванов'))
22
+ assert(!Student.valid_name?('Сидоров-Петров'))
23
+ assert(!Student.valid_name?('X'))
24
+ assert(Student.valid_name?('Abcdefghijklmnopqrstuvwxyz'))
25
+ assert(!Student.valid_name?(''))
26
+ assert(!Student.valid_name?('Иванов 123'))
27
+ assert(!Student.valid_name?('Иванов.'))
28
+ assert(!Student.valid_name?('-Иванов'))
29
+ end
30
+
31
+ def test_from_hash
32
+ hash = {
33
+ first_name: 'Иван',
34
+ last_name: 'Иванов',
35
+ father_name: 'Иванович',
36
+ phone: '+79991234567',
37
+ telegram: 'ivanov',
38
+ email: 'ivanov@example.com',
39
+ git: 'ivanov'
40
+ }
41
+ student = Student.from_hash(hash)
42
+ assert_equal(hash[:first_name], student.first_name)
43
+ assert_equal(hash[:last_name], student.last_name)
44
+ assert_equal(hash[:father_name], student.father_name)
45
+ assert_equal(hash[:phone], student.phone)
46
+ assert_equal(hash[:telegram], student.telegram)
47
+ assert_equal(hash[:email], student.email)
48
+ assert_equal(hash[:git], student.git)
49
+ end
50
+
51
+ def test_from_json_str
52
+ hash = {
53
+ first_name: 'Иван',
54
+ last_name: 'Иванов',
55
+ father_name: 'Иванович',
56
+ phone: '+79991234567',
57
+ telegram: 'ivanov',
58
+ email: 'ivanov@example.com',
59
+ git: 'ivanov'
60
+ }
61
+ json_str = hash.to_json
62
+ student = Student.from_json_str(json_str)
63
+ assert_equal(hash[:first_name], student.first_name)
64
+ assert_equal(hash[:last_name], student.last_name)
65
+ assert_equal(hash[:father_name], student.father_name)
66
+ assert_equal(hash[:phone], student.phone)
67
+ assert_equal(hash[:telegram], student.telegram)
68
+ assert_equal(hash[:email], student.email)
69
+ assert_equal(hash[:git], student.git)
70
+ end
71
+ end
@@ -0,0 +1,54 @@
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
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './LabStudents/repositories/containers/data_table'
4
+
5
+ class DataList
6
+ # Это "абстрактный" класс
7
+ private_class_method :new
8
+
9
+ attr_writer :objects
10
+
11
+ # Конструктор, принимает массив любых объектов
12
+ def initialize(objects)
13
+ self.objects = objects
14
+ @listeners = []
15
+ end
16
+
17
+ def add_listener(listener)
18
+ @listeners << listener
19
+ end
20
+
21
+ def remove_listener(listener)
22
+ @listeners.delete(listener)
23
+ end
24
+
25
+ def notify
26
+ @listeners.each { |lst| lst.on_datalist_changed(data_table) }
27
+ end
28
+
29
+ # Выбрать элемент по номеру
30
+ def select_element(number)
31
+ self.selected_num = number < objects.size ? number : nil
32
+ end
33
+
34
+ def selected_id
35
+ objects[selected_num].id
36
+ end
37
+
38
+ # Получить DataTable со всеми элементами.
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
+ # Добавить элементы в конец списка
53
+ def replace_objects(objects)
54
+ self.objects = objects.dup
55
+ notify
56
+ end
57
+
58
+ protected
59
+
60
+ # Список значений полей для DataTable. Переопределить в наследниках
61
+ def table_fields(_obj)
62
+ []
63
+ end
64
+
65
+ # Имена атрибутов объектов по порядку. Переопределить в наследниках
66
+ def column_names
67
+ []
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :objects
73
+ attr_accessor :selected_num
74
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'data_list'
4
+
5
+ class DataListStudentShort < DataList
6
+ # Делаем приватный new предка публичным
7
+ public_class_method :new
8
+
9
+ def column_names
10
+ ['Фамилия И. О.', 'Гит', 'Контакт']
11
+ end
12
+
13
+ protected
14
+
15
+ def table_fields(obj)
16
+ [obj.last_name_and_initials, obj.git, obj.contact]
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DataTable
4
+ attr_reader :rows_count, :cols_count
5
+
6
+ # Конструктор, принимает 2D Array
7
+ def initialize(table)
8
+ self.rows_count = table.size
9
+ max_cols = 0
10
+ table.each { |row| max_cols = row.size if row.size > max_cols }
11
+ self.cols_count = max_cols
12
+ self.table = table
13
+ end
14
+
15
+ # Получить значение в ячейке [row, col]
16
+ def get_item(row, col)
17
+ return nil if row >= rows_count
18
+ return nil if col >= cols_count
19
+
20
+ table[row][col].dup
21
+ end
22
+
23
+ def to_2d_array
24
+ table.dup
25
+ end
26
+
27
+ def to_s
28
+ "DataTable (#{rows_count}x#{cols_count})"
29
+ end
30
+
31
+ private
32
+
33
+ attr_accessor :table
34
+ attr_writer :rows_count, :cols_count
35
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mysql2'
4
+
5
+ class DBDataSource
6
+ private_class_method :new
7
+ @instance_mutex = Mutex.new
8
+
9
+ def initialize
10
+ db_config = YAML.load_file('./LabStudents/db_config/config.yaml').transform_keys(&:to_sym)
11
+ @client = Mysql2::Client.new(db_config)
12
+ @client.query_options.merge!(symbolize_keys: true)
13
+ end
14
+
15
+ def self.instance
16
+ return @instance if @instance
17
+
18
+ @instance_mutex.synchronize do
19
+ @instance ||= new
20
+ end
21
+
22
+ @instance
23
+ end
24
+
25
+ def prepare_exec(statement, *params)
26
+ @client.prepare(statement).execute(*params)
27
+ end
28
+
29
+ def query(statement)
30
+ @client.query(statement)
31
+ end
32
+
33
+ def last_id
34
+ @client.last_id
35
+ end
36
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './LabStudents/models/student'
4
+ require './LabStudents/models/student_short'
5
+ require './LabStudents/repositories/containers/data_list_student_short'
6
+
7
+ class FileDataSource
8
+ attr_writer :data_transformer
9
+
10
+ def initialize(data_transformer)
11
+ self.students = []
12
+ self.seq_id = 1
13
+ self.data_transformer = data_transformer
14
+ end
15
+
16
+ def load_from_file(file_path)
17
+ hash_list = data_transformer.str_to_hash_list(File.read(file_path))
18
+ self.students = hash_list.map { |h| Student.from_hash(h) }
19
+ update_seq_id
20
+ end
21
+
22
+ def save_to_file(file_path)
23
+ hash_list = students.map(&:to_hash)
24
+ File.write(file_path, data_transformer.hash_list_to_str(hash_list))
25
+ end
26
+
27
+ def student_by_id(student_id)
28
+ students.detect { |s| s.id == student_id }
29
+ end
30
+
31
+ # Получить page по счету count элементов (страница начинается с 1)
32
+ def paginated_short_students(page, count, existing_data_list = nil)
33
+ offset = (page - 1) * count
34
+ slice = students[offset, count].map { |s| StudentShort.from_student(s) }
35
+
36
+ return DataListStudentShort.new(slice) if existing_data_list.nil?
37
+
38
+ existing_data_list.replace_objects(slice)
39
+ existing_data_list
40
+ end
41
+
42
+ def sorted
43
+ students.sort_by(&:last_name_and_initials)
44
+ end
45
+
46
+ def add_student(student)
47
+ student.id = seq_id
48
+ students << student
49
+ self.seq_id += 1
50
+ student.id
51
+ end
52
+
53
+ def replace_student(student_id, student)
54
+ idx = students.find_index { |s| s.id == student_id }
55
+ students[idx] = student
56
+ end
57
+
58
+ def remove_student(student_id)
59
+ students.reject! { |s| s.id == student_id }
60
+ end
61
+
62
+ def student_count
63
+ students.count
64
+ end
65
+
66
+ private
67
+
68
+ # Метод для актуализации seq_id
69
+ def update_seq_id
70
+ self.seq_id = students.max_by(&:id).id + 1
71
+ end
72
+
73
+ attr_reader :data_transformer
74
+ attr_accessor :students, :seq_id
75
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DataTransformerBase
4
+ private_class_method :new
5
+
6
+ protected
7
+
8
+ def str_to_hash_list(str)
9
+ raise NotImplementedError('Should be implemented in child')
10
+ end
11
+
12
+ def hash_list_to_str(hash_list)
13
+ raise NotImplementedError('Should be implemented in child')
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'data_transformer_base'
4
+ require 'json'
5
+
6
+ class DataTransformerJSON < DataTransformerBase
7
+ public_class_method :new
8
+
9
+ def str_to_hash_list(str)
10
+ JSON.parse(str, { symbolize_names: true })
11
+ end
12
+
13
+ def hash_list_to_str(hash_list)
14
+ JSON.pretty_generate(hash_list)
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'data_transformer_base'
4
+ require 'yaml'
5
+
6
+ class DataTransformerYAML < DataTransformerBase
7
+ public_class_method :new
8
+
9
+ def str_to_hash_list(str)
10
+ YAML.safe_load(str).map { |h| h.transform_keys(&:to_sym) }
11
+ end
12
+
13
+ def hash_list_to_str(hash_list)
14
+ hash_list.map { |h| h.transform_keys(&:to_s) }.to_yaml
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StudentRepository
4
+ def initialize(data_source_adapter)
5
+ @data_source_adapter = data_source_adapter
6
+ end
7
+
8
+ def student_by_id(student_id)
9
+ @data_source_adapter.student_by_id(student_id)
10
+ end
11
+
12
+ # Получить page по счету count элементов (страница начинается с 1)
13
+ def paginated_short_students(page, count, existing_data_list = nil)
14
+ @data_source_adapter.paginated_short_students(page, count, existing_data_list)
15
+ end
16
+
17
+ def add_student(student)
18
+ @data_source_adapter.add_student(student)
19
+ end
20
+
21
+ def replace_student(student_id, student)
22
+ @data_source_adapter.replace_student(student_id, student)
23
+ end
24
+
25
+ def remove_student(student_id)
26
+ @data_source_adapter.remove_student(student_id)
27
+ end
28
+
29
+ def student_count
30
+ @data_source_adapter.student_count
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ class LoggerHolder
6
+ private_class_method :new
7
+ @instance_mutex = Mutex.new
8
+
9
+ attr_reader :logger
10
+
11
+ def initialize
12
+ @logger = Logger.new(STDOUT)
13
+ end
14
+
15
+ def self.instance
16
+ return @instance.logger if @instance
17
+
18
+ @instance_mutex.synchronize do
19
+ @instance ||= new
20
+ end
21
+
22
+ @instance.logger
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rubbish_code/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rubbish_code"
7
+ spec.version = RubbishCode::VERSION
8
+ spec.authors = ["Jake Epps"]
9
+ spec.email = ["nullexp.team@gmail.com"]
10
+ spec.summary = "Student App"
11
+ spec.description = "А gem that allows you to get pass for patterns"
12
+ spec.homepage = "https://github.com/Jakepps/Ruby_Moment"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 3.2.0"
15
+ spec.add_dependency 'win32api'
16
+ spec.files = Dir.glob("**/*")
17
+ end
@@ -0,0 +1,4 @@
1
+ module RubbishCode
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubbish_code
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Epps
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-05 00:00:00.000000000 Z
11
+ date: 2023-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: win32api
@@ -25,19 +25,44 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: А gem that allows you to get pass for patterns
28
- email: nullexp.team@gmail.com
28
+ email:
29
+ - nullexp.team@gmail.com
29
30
  executables: []
30
31
  extensions: []
31
32
  extra_rdoc_files: []
32
33
  files:
34
+ - CHANGELOG.md
35
+ - CODE_OF_CONDUCT.md
36
+ - Documentation.md
37
+ - Gemfile
33
38
  - LICENSE.txt
34
39
  - README.md
35
- - lib/controllers/student_input_form/student_input_form_controller_create.rb
36
- - lib/controllers/student_input_form/student_input_form_controller_edit.rb
37
- - lib/controllers/tab_students_controller.rb
38
- - lib/models/student.rb
39
- - lib/models/student_base.rb
40
- - lib/models/student_short.rb
40
+ - lib/rubbish_code.rb
41
+ - lib/rubbish_code/version.rb
42
+ - lib/source/controllers/student_input_form/student_input_form_controller_create.rb
43
+ - lib/source/controllers/student_input_form/student_input_form_controller_edit.rb
44
+ - lib/source/controllers/tab_students_controller.rb
45
+ - lib/source/db_config/config.yaml
46
+ - lib/source/db_config/migrations/001_create_table_student.sql
47
+ - lib/source/db_config/mock_data/fill_student.sql
48
+ - lib/source/models/student.rb
49
+ - lib/source/models/student_base.rb
50
+ - lib/source/models/student_short.rb
51
+ - lib/source/models/student_test.rb
52
+ - lib/source/repositories/adapters/db_source_adapter.rb
53
+ - lib/source/repositories/adapters/file_source_adapter.rb
54
+ - lib/source/repositories/containers/data_list.rb
55
+ - lib/source/repositories/containers/data_list_student_short.rb
56
+ - lib/source/repositories/containers/data_table.rb
57
+ - lib/source/repositories/data_sources/db_data_source.rb
58
+ - lib/source/repositories/data_sources/file_data_source.rb
59
+ - lib/source/repositories/data_sources/transformers/data_transformer_base.rb
60
+ - lib/source/repositories/data_sources/transformers/data_transformer_json.rb
61
+ - lib/source/repositories/data_sources/transformers/data_transformer_yaml.rb
62
+ - lib/source/repositories/student_repository.rb
63
+ - lib/source/util/logger_holder.rb
64
+ - rubbish_code.gemspec
65
+ - sig/ribbish_code.rbs
41
66
  homepage: https://github.com/Jakepps/Ruby_Moment
42
67
  licenses:
43
68
  - MIT
@@ -50,7 +75,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
75
  requirements:
51
76
  - - ">="
52
77
  - !ruby/object:Gem::Version
53
- version: '0'
78
+ version: 3.2.0
54
79
  required_rubygems_version: !ruby/object:Gem::Requirement
55
80
  requirements:
56
81
  - - ">="
File without changes
File without changes
File without changes