jewerly_system 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +84 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +1 -0
  6. data/jewelry_system.gemspec +17 -0
  7. data/lib/jewerly_system/version.rb +5 -0
  8. data/lib/jewerly_system.rb +10 -0
  9. data/lib/source/customer/controllers/customer_input_form_controller_create.rb +44 -0
  10. data/lib/source/customer/controllers/customer_input_form_controller_edit.rb +52 -0
  11. data/lib/source/customer/controllers/customer_list_controller.rb +104 -0
  12. data/lib/source/customer/customer_db_data_source.rb +63 -0
  13. data/lib/source/customer/ui/customer_input_form.rb +70 -0
  14. data/lib/source/customer/ui/customer_list_view.rb +159 -0
  15. data/lib/source/master/controllers/master_controller.rb +57 -0
  16. data/lib/source/master/controllers/master_input_form_controller_create.rb +44 -0
  17. data/lib/source/master/controllers/master_input_form_controller_edit.rb +53 -0
  18. data/lib/source/master/controllers/master_list_controller.rb +101 -0
  19. data/lib/source/master/master_db_data_source.rb +65 -0
  20. data/lib/source/master/ui/master_input_form.rb +72 -0
  21. data/lib/source/master/ui/master_list_view.rb +163 -0
  22. data/lib/source/models/customer.rb +37 -0
  23. data/lib/source/models/master.rb +32 -0
  24. data/lib/source/models/product.rb +31 -0
  25. data/lib/source/models/student.rb +102 -0
  26. data/lib/source/models/student_base.rb +100 -0
  27. data/lib/source/models/student_short.rb +50 -0
  28. data/lib/source/state_holders/list_state_notifier.rb +47 -0
  29. data/lib/source/util/logger_holder.rb +24 -0
  30. data/sig/jewerly_system.rbs +4 -0
  31. metadata +86 -0
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative 'student_base'
5
+
6
+ class Student < StudentBase
7
+ # Делаем new предка публичным
8
+ public_class_method :new
9
+
10
+ def self.from_hash(hash)
11
+ raise ArgumentError, 'Fields required: fist_name, last_name, father_name' unless hash.key?(:first_name) && hash.key?(:last_name) && hash.key?(:father_name)
12
+
13
+ first_name = hash.delete(:first_name)
14
+ last_name = hash.delete(:last_name)
15
+ father_name = hash.delete(:father_name)
16
+
17
+ Student.new(last_name, first_name, father_name, **hash)
18
+ end
19
+
20
+ # Конструктор из JSON строки
21
+ def self.from_json_str(str)
22
+ params = JSON.parse(str, { symbolize_names: true })
23
+ from_hash(params)
24
+ end
25
+
26
+ # Делаем публичными геттеры и сеттеры базового класса
27
+ public :phone, :telegram, :email, 'id=', 'phone=', 'telegram=', 'email=', 'git='
28
+
29
+ # Стандартные геттеры для полей
30
+ attr_reader :last_name, :first_name, :father_name
31
+
32
+ # Стандартный конструктор
33
+ def initialize(last_name, first_name, father_name, **options)
34
+ self.last_name = last_name
35
+ self.first_name = first_name
36
+ self.father_name = father_name
37
+ super(**options)
38
+ end
39
+
40
+ # Сеттеры с валидацией перед присваиванием
41
+ def last_name=(new_last_name)
42
+ raise ArgumentError, "Invalid argument: last_name=#{new_last_name}" unless Student.valid_name?(new_last_name)
43
+
44
+ @last_name = new_last_name
45
+ end
46
+
47
+ def first_name=(new_first_name)
48
+ raise ArgumentError, "Invalid argument: first_name=#{new_first_name}" unless Student.valid_name?(new_first_name)
49
+
50
+ @first_name = new_first_name
51
+ end
52
+
53
+ def father_name=(new_father_name)
54
+ raise ArgumentError, "Invalid argument: father_name=#{new_father_name}" unless Student.valid_name?(new_father_name)
55
+
56
+ @father_name = new_father_name
57
+ end
58
+
59
+ # Отдельный сеттер для массовой установки контактов
60
+ def set_contacts(phone: nil, telegram: nil, email: nil)
61
+ self.phone = phone if phone
62
+ self.telegram = telegram if telegram
63
+ self.email = email if email
64
+ end
65
+
66
+ # Имя пользователя в формате Фамилия И. О.
67
+ def last_name_and_initials
68
+ "#{last_name} #{first_name[0]}. #{father_name[0]}."
69
+ end
70
+
71
+ # Краткая информация о пользователе
72
+ def short_info
73
+ info = {}
74
+ info[:last_name_and_initials] = last_name_and_initials
75
+ info[:contact] = short_contact
76
+ info[:git] = git
77
+ JSON.generate(info)
78
+ end
79
+
80
+ # Методы приведения объекта к строке
81
+ def to_s
82
+ result = "#{last_name} #{first_name} #{father_name}"
83
+ %i[id phone telegram email git].each do |attr|
84
+ attr_val = send(attr)
85
+ result += ", #{attr}=#{attr_val}" unless attr_val.nil?
86
+ end
87
+ result
88
+ end
89
+
90
+ def to_hash
91
+ attrs = {}
92
+ %i[last_name first_name father_name id phone telegram email git].each do |attr|
93
+ attr_val = send(attr)
94
+ attrs[attr] = attr_val unless attr_val.nil?
95
+ end
96
+ attrs
97
+ end
98
+
99
+ def to_json_str
100
+ JSON.generate(to_hash)
101
+ end
102
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StudentBase
4
+ # Запрещаем создание базового класса (он "абстрактный")
5
+ private_class_method :new
6
+
7
+ # Валидаторы для полей
8
+ def self.valid_name?(name)
9
+ name.match(/(^[А-Я][а-я]+$)|(^[A-Z][a-z]+$)/)
10
+ end
11
+
12
+ def self.valid_phone?(phone)
13
+ phone.match(/^\+?[78] ?[(-]?\d{3} ?[)-]?[ -]?\d{3}[ -]?\d{2}[ -]?\d{2}$/)
14
+ end
15
+
16
+ def self.valid_profile_name?(profile_name)
17
+ profile_name.match(/^[a-zA-Z0-9_.]+$/)
18
+ end
19
+
20
+ def self.valid_email?(email)
21
+ email.match(/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/)
22
+ end
23
+
24
+ # Стандартные геттеры и сеттеры для полей
25
+
26
+ protected
27
+
28
+ attr_writer :id
29
+ attr_reader :phone, :telegram, :email
30
+
31
+ public
32
+
33
+ attr_reader :id, :git
34
+
35
+ # Стандартный конструктор
36
+ def initialize(id: nil, phone: nil, telegram: nil, email: nil, git: nil)
37
+ self.id = id
38
+ self.phone = phone
39
+ self.telegram = telegram
40
+ self.email = email
41
+ self.git = git
42
+ end
43
+
44
+ # Краткая информация о первом доступном контакте пользователя
45
+ def short_contact
46
+ contact = {}
47
+ %i[telegram email phone].each do |attr|
48
+ attr_val = send(attr)
49
+ next if attr_val.nil?
50
+
51
+ contact[:type] = attr
52
+ contact[:value] = attr_val
53
+ return contact
54
+ end
55
+
56
+ nil
57
+ end
58
+
59
+ protected
60
+
61
+ # Сеттеры с валидацией перед присваиванием
62
+ def phone=(new_phone)
63
+ raise ArgumentError, "Invalid argument: phone=#{new_phone}" unless new_phone.nil? || StudentBase.valid_phone?(new_phone)
64
+
65
+ @phone = new_phone
66
+ end
67
+
68
+ def telegram=(new_telegram)
69
+ raise ArgumentError, "Invalid argument: telegram=#{new_telegram}" unless new_telegram.nil? || StudentBase.valid_profile_name?(new_telegram)
70
+
71
+ @telegram = new_telegram
72
+ end
73
+
74
+ def git=(new_git)
75
+ raise ArgumentError, "Invalid argument: git=#{new_git}" unless new_git.nil? || StudentBase.valid_profile_name?(new_git)
76
+
77
+ @git = new_git
78
+ end
79
+
80
+ def email=(new_email)
81
+ raise ArgumentError, "Invalid argument: email=#{new_email}" unless new_email.nil? || StudentBase.valid_email?(new_email)
82
+
83
+ @email = new_email
84
+ end
85
+
86
+ public
87
+
88
+ # Валидаторы объекта
89
+ def has_contacts?
90
+ !phone.nil? || !telegram.nil? || !email.nil?
91
+ end
92
+
93
+ def has_git?
94
+ !git.nil?
95
+ end
96
+
97
+ def valid?
98
+ has_contacts? && has_git?
99
+ end
100
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StudentShort < StudentBase
4
+ # Делаем new предка публичным
5
+ public_class_method :new
6
+
7
+ # Стандартные геттеры и сеттеры
8
+
9
+ private
10
+
11
+ attr_writer :last_name_and_initials, :contact
12
+
13
+ public
14
+
15
+ attr_reader :last_name_and_initials, :contact
16
+
17
+ # Конструктор из Student
18
+ def self.from_student(student)
19
+ raise ArgumentError, 'Student ID is required' if student.id.nil?
20
+
21
+ StudentShort.new(student.id, student.short_info)
22
+ end
23
+
24
+ # Стандартный конструктор
25
+ def initialize(id, info_str)
26
+ params = JSON.parse(info_str, { symbolize_names: true })
27
+ raise ArgumentError, 'Fields required: last_name_and_initials' if !params.key?(:last_name_and_initials) || params[:last_name_and_initials].nil?
28
+
29
+ self.id = id
30
+ self.last_name_and_initials = params[:last_name_and_initials]
31
+ self.contact = params[:contact]
32
+ self.git = params[:git]
33
+
34
+ options = {}
35
+ options[:id] = id
36
+ options[:git] = git
37
+ options[contact[:type].to_sym] = contact[:value] if contact
38
+ super(**options)
39
+ end
40
+
41
+ # Методы приведения объекта к строке
42
+ def to_s
43
+ result = last_name_and_initials
44
+ %i[id contact git].each do |attr|
45
+ attr_val = send(attr)
46
+ result += ", #{attr}=#{attr_val}" unless attr_val.nil?
47
+ end
48
+ result
49
+ end
50
+ end
@@ -0,0 +1,47 @@
1
+ class ListStateNotifier
2
+ attr_reader :items
3
+
4
+ def initialize
5
+ @items = []
6
+ @listeners = []
7
+ end
8
+
9
+ def set_all(objects)
10
+ @items = objects
11
+ notify_listeners
12
+ end
13
+
14
+ def add(object)
15
+ @items << object
16
+ notify_listeners
17
+ end
18
+
19
+ def get(number)
20
+ @items[number]
21
+ end
22
+
23
+ def delete(object)
24
+ @items.delete(object)
25
+ notify_listeners
26
+ end
27
+
28
+ def replace(object, new_object)
29
+ index = @items.index(object)
30
+ @items[index] = new_object
31
+ notify_listeners
32
+ end
33
+
34
+ def add_listener(listener)
35
+ @listeners << listener
36
+ end
37
+
38
+ def delete_listener(listener)
39
+ @listeners.delete(listener)
40
+ end
41
+
42
+ def notify_listeners
43
+ @listeners.each do |listener|
44
+ listener.update(@items)
45
+ end
46
+ end
47
+ 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,4 @@
1
+ module RubbishCode
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jewerly_system
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jake Epps
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-05-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mysql2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: А gem that allows you to get pass for patterns
28
+ email:
29
+ - nullexp.team@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CODE_OF_CONDUCT.md
35
+ - Gemfile
36
+ - LICENSE.txt
37
+ - README.md
38
+ - jewelry_system.gemspec
39
+ - lib/jewerly_system.rb
40
+ - lib/jewerly_system/version.rb
41
+ - lib/source/customer/controllers/customer_input_form_controller_create.rb
42
+ - lib/source/customer/controllers/customer_input_form_controller_edit.rb
43
+ - lib/source/customer/controllers/customer_list_controller.rb
44
+ - lib/source/customer/customer_db_data_source.rb
45
+ - lib/source/customer/ui/customer_input_form.rb
46
+ - lib/source/customer/ui/customer_list_view.rb
47
+ - lib/source/master/controllers/master_controller.rb
48
+ - lib/source/master/controllers/master_input_form_controller_create.rb
49
+ - lib/source/master/controllers/master_input_form_controller_edit.rb
50
+ - lib/source/master/controllers/master_list_controller.rb
51
+ - lib/source/master/master_db_data_source.rb
52
+ - lib/source/master/ui/master_input_form.rb
53
+ - lib/source/master/ui/master_list_view.rb
54
+ - lib/source/models/customer.rb
55
+ - lib/source/models/master.rb
56
+ - lib/source/models/product.rb
57
+ - lib/source/models/student.rb
58
+ - lib/source/models/student_base.rb
59
+ - lib/source/models/student_short.rb
60
+ - lib/source/state_holders/list_state_notifier.rb
61
+ - lib/source/util/logger_holder.rb
62
+ - sig/jewerly_system.rbs
63
+ homepage: https://github.com/Jakepps/Ruby_Moment
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 3.4.10
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Jewerly App
86
+ test_files: []