students_list_yaml_Quartz 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/lib/Base.rb +35 -0
- data/lib/README.rdoc +164 -0
- data/lib/Rakefile.rb +15 -0
- data/lib/Students_list_JSON.rb +86 -0
- data/lib/data_list.rb +75 -0
- data/lib/data_list_Student_short.rb +18 -0
- data/lib/data_table.rb +17 -0
- data/lib/student.rb +185 -0
- data/lib/student_short.rb +26 -0
- data/lib/students_list_yaml/version.rb +3 -0
- data/lib/students_list_yaml.rb +93 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 95c6092475db21fe4c65f122426f93af80bad40716d3c43a612ffd7a9b6700ae
|
|
4
|
+
data.tar.gz: 33fcb5592ee4b4c9922537ce5c9e9c43d1850714764cbbe23200c156a77789ad
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8cc4a7aae5c8d4013323fd639e12246ff77e3342742ca44070c576283d46fe842cfbaad8cc5a5ca2682b652daa67e3387b32ac99d9d36ddbecc38e4c9015d90a
|
|
7
|
+
data.tar.gz: 378290c9c17c7685a217cac342d3a18ec74c53890644836ccc1c58a60d8767cfaf21165047f2dab2f09c73848ac63a65427c83df49e857c00cafe22b8bdadf23
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Quartz
|
|
4
|
+
|
|
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:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# StudentsListYaml
|
|
2
|
+
|
|
3
|
+
TODO: Delete this and the text below, and describe your gem
|
|
4
|
+
|
|
5
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/students_list_yaml`. To experiment with that code, run `bin/console` for an interactive prompt.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
10
|
+
|
|
11
|
+
Install the gem and add to the application's Gemfile by executing:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
TODO: Write usage instructions here
|
|
26
|
+
|
|
27
|
+
## Development
|
|
28
|
+
|
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
30
|
+
|
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
32
|
+
|
|
33
|
+
## Contributing
|
|
34
|
+
|
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/students_list_yaml. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/students_list_yaml/blob/master/CODE_OF_CONDUCT.md).
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
40
|
+
|
|
41
|
+
## Code of Conduct
|
|
42
|
+
|
|
43
|
+
Everyone interacting in the StudentsListYaml project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/students_list_yaml/blob/master/CODE_OF_CONDUCT.md).
|
data/lib/Base.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class Base
|
|
2
|
+
|
|
3
|
+
def git
|
|
4
|
+
@git
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def id
|
|
8
|
+
@id
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def contact
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def short_info
|
|
20
|
+
string = "id: #{id.to_s}, ФИО: #{last_name_initials}, гит: #{git}, контакт: #{contact}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def has_git?
|
|
24
|
+
@git!=nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def has_contact?
|
|
28
|
+
contact!=nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def last_name_initials
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
data/lib/README.rdoc
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
= Students_list_JSON — README
|
|
2
|
+
|
|
3
|
+
== Описание
|
|
4
|
+
Класс Students_list_JSON — лёгкий Ruby-класс для управления коллекцией студентов, сериализуемой в JSON.
|
|
5
|
+
Обеспечивает загрузку/сохранение из/в файла, CRUD-операции, постраничную выдачу сокращённых представлений (StudentShort) и сортировку.
|
|
6
|
+
|
|
7
|
+
== Требования
|
|
8
|
+
|
|
9
|
+
Ruby 2.5+ (или совместимая).
|
|
10
|
+
|
|
11
|
+
Стандартная библиотека json.
|
|
12
|
+
|
|
13
|
+
В проекте должны присутствовать файлы:
|
|
14
|
+
|
|
15
|
+
student.rb — класс Student.
|
|
16
|
+
|
|
17
|
+
student_short.rb — класс StudentShort.
|
|
18
|
+
|
|
19
|
+
data_list_student_short.rb — класс DataListStudentShort (или общий DataList).
|
|
20
|
+
|
|
21
|
+
== Установка
|
|
22
|
+
Поместите файл students_list_json.rb в проект и подключите:
|
|
23
|
+
|
|
24
|
+
require_relative 'students_list_json'
|
|
25
|
+
require_relative 'student'
|
|
26
|
+
require_relative 'student_short'
|
|
27
|
+
require_relative 'data_list_student_short'
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
== Быстрый старт — пример использования
|
|
31
|
+
|
|
32
|
+
# инициализация (загрузка при наличии файла)
|
|
33
|
+
list = Students_list_JSON.new('students.json')
|
|
34
|
+
|
|
35
|
+
# добавление студента (предполагается реализация Student.from_hash/to_hash)
|
|
36
|
+
student = Student.from_hash(first_name: 'Ivan', last_name: 'Ivanov')
|
|
37
|
+
added = list.add_student(student)
|
|
38
|
+
puts "Добавлен студент с id=#{added.id}"
|
|
39
|
+
|
|
40
|
+
# сохранить в файл
|
|
41
|
+
list.save_to_file
|
|
42
|
+
|
|
43
|
+
# получить первого студента по id
|
|
44
|
+
s = list.get_student_by_id(1)
|
|
45
|
+
puts s.to_hash if s
|
|
46
|
+
|
|
47
|
+
# постраничная выдача — 10 элементов, страница 1
|
|
48
|
+
page = list.get_k_n_student_short_list(10, 1)
|
|
49
|
+
puts page.data.map(&:to_hash)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
== API (краткое описание методов)
|
|
53
|
+
|
|
54
|
+
Students_list_JSON.new(file_path = nil) — конструктор; при наличии существующего file_path автоматически выполняет загрузку.
|
|
55
|
+
|
|
56
|
+
load_from_file — загрузка списка из @file_path. При некорректном JSON внутренний список очищается.
|
|
57
|
+
|
|
58
|
+
save_to_file — сохраняет @students в @file_path в виде pretty JSON.
|
|
59
|
+
|
|
60
|
+
get_student_by_id(id) — возвращает Student или nil.
|
|
61
|
+
|
|
62
|
+
get_k_n_student_short_list(k, n, existing_data_list = nil) — возвращает постраничный список StudentShort. Если передан existing_data_list типа DataList, его поле data перезаписывается.
|
|
63
|
+
|
|
64
|
+
sort_by_full_name — сортирует внутренний массив по last_name_initials.downcase.
|
|
65
|
+
|
|
66
|
+
add_student(student) — добавляет студента, генерирует уникальный id, возвращает добавленный объект.
|
|
67
|
+
|
|
68
|
+
replace_student_by_id(id, new_student) — заменяет студента с указанным id; возвращает true/false.
|
|
69
|
+
|
|
70
|
+
delete_student_by_id(id) — удаляет студента(ов) по id; возвращает true/false.
|
|
71
|
+
|
|
72
|
+
get_student_short_count — возвращает количество студентов (Integer).
|
|
73
|
+
|
|
74
|
+
== Формат JSON (ожидаемый)
|
|
75
|
+
Класс ожидает JSON-массив объектов, каждый объект — структура, совместимая с Student.from_hash и Student#to_hash.
|
|
76
|
+
Пример:
|
|
77
|
+
|
|
78
|
+
[
|
|
79
|
+
{"id":1,"first_name":"Ivan","last_name":"Ivanov","birth_date":"2000-01-01","group":"CS-101"},
|
|
80
|
+
{"id":2,"first_name":"Anna","last_name":"Petrova","birth_date":"1999-05-12","group":"CS-101"}
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
== Ожидаемый интерфейс зависимых классов
|
|
85
|
+
Чтобы Students_list_JSON работал, зависимые классы должны поддерживать:
|
|
86
|
+
|
|
87
|
+
Student
|
|
88
|
+
|
|
89
|
+
.from_hash(hash) — создать объект из хэша.
|
|
90
|
+
|
|
91
|
+
#to_hash — вернуть хэш для сериализации.
|
|
92
|
+
|
|
93
|
+
#id — числовой идентификатор.
|
|
94
|
+
|
|
95
|
+
#last_name_initials — строка для сортировки (например, "Ivanov I.P.").
|
|
96
|
+
|
|
97
|
+
StudentShort
|
|
98
|
+
|
|
99
|
+
.from_student(student) — создать сокращённое представление.
|
|
100
|
+
|
|
101
|
+
#to_hash — (опционально) для сериализации.
|
|
102
|
+
|
|
103
|
+
DataListStudentShort / DataList
|
|
104
|
+
|
|
105
|
+
Конструктор DataListStudentShort.new(array_of_short_students) или объект с присваиваемым полем data для записи массива StudentShort.
|
|
106
|
+
|
|
107
|
+
== Поведение и ошибки
|
|
108
|
+
|
|
109
|
+
При JSON::ParserError — внутренний список очищается (чтобы избежать неконсистентных данных).
|
|
110
|
+
|
|
111
|
+
Если file_path не указан — операции загрузки/сохранения игнорируются.
|
|
112
|
+
|
|
113
|
+
get_k_n_student_short_list безопасно возвращает пустой список, если индекс выходит за пределы.
|
|
114
|
+
|
|
115
|
+
replace_student_by_id и delete_student_by_id возвращают логические значения, не выбрасывают исключения при отсутствии записи.
|
|
116
|
+
|
|
117
|
+
== Рекомендации по улучшению
|
|
118
|
+
|
|
119
|
+
Добавить логирование ошибок при парсинге JSON вместо тихого rescue.
|
|
120
|
+
|
|
121
|
+
Ввести валидацию входных объектов (проверять наличие to_hash, id и т.п.).
|
|
122
|
+
|
|
123
|
+
Для многопоточных приложений — использовать Mutex для защиты @students.
|
|
124
|
+
|
|
125
|
+
Валидация схемы JSON (gem json-schema или аналог).
|
|
126
|
+
|
|
127
|
+
== Генерация RDoc-документации
|
|
128
|
+
|
|
129
|
+
Убедитесь, что у вас установлен rdoc (если нет — gem install rdoc).
|
|
130
|
+
|
|
131
|
+
В каталоге с проектом выполните:
|
|
132
|
+
|
|
133
|
+
rdoc -o doc students_list_json.rb student.rb student_short.rb data_list_student_short.rb
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
Откройте doc/index.html в браузере.
|
|
137
|
+
|
|
138
|
+
Для генерации документации по всему проекту (включая README) выполните:
|
|
139
|
+
|
|
140
|
+
rdoc -o doc .
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
== Тестирование
|
|
144
|
+
Рекомендуется покрыть тестами (RSpec/Minitest) сценарии:
|
|
145
|
+
|
|
146
|
+
* загрузка корректного JSON;
|
|
147
|
+
|
|
148
|
+
* поведение при некорректном JSON;
|
|
149
|
+
|
|
150
|
+
* добавление/замена/удаление студентов;
|
|
151
|
+
|
|
152
|
+
* постраничная выдача и граничные условия;
|
|
153
|
+
|
|
154
|
+
* сохранение и повторная загрузка.
|
|
155
|
+
|
|
156
|
+
== Лицензия
|
|
157
|
+
Добавьте подходящую лицензию (например, MIT). Примерный блок для LICENSE:
|
|
158
|
+
|
|
159
|
+
MIT License
|
|
160
|
+
Copyright (c) <year> <author>
|
|
161
|
+
...
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
== Контакты / автор
|
data/lib/Rakefile.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'rdoc/task'
|
|
2
|
+
|
|
3
|
+
RDoc::Task.new do |rdoc|
|
|
4
|
+
rdoc.title = "StudentListJSON Documentation"
|
|
5
|
+
rdoc.rdoc_dir = 'doc'
|
|
6
|
+
rdoc.main = 'README.rdoc'
|
|
7
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
8
|
+
rdoc.rdoc_files.include('Students_list_JSON.rb')
|
|
9
|
+
rdoc.rdoc_files.include('examples/*.rb')
|
|
10
|
+
|
|
11
|
+
rdoc.options << '--all'
|
|
12
|
+
rdoc.options << '--fmt=html'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
task :default => :rdoc
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require_relative 'student'
|
|
3
|
+
require_relative 'student_short'
|
|
4
|
+
require_relative 'data_list'
|
|
5
|
+
|
|
6
|
+
class Students_list_JSON
|
|
7
|
+
attr_reader :file_path
|
|
8
|
+
|
|
9
|
+
def initialize(file_path = nil)
|
|
10
|
+
@file_path = file_path
|
|
11
|
+
@students = []
|
|
12
|
+
load_from_file if file_path && File.exist?(file_path)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def load_from_file
|
|
16
|
+
return unless @file_path && File.exist?(@file_path)
|
|
17
|
+
|
|
18
|
+
begin
|
|
19
|
+
content = File.read(@file_path)
|
|
20
|
+
return if content.strip.empty?
|
|
21
|
+
|
|
22
|
+
data = JSON.parse(content, symbolize_names: true)
|
|
23
|
+
@students = data.map { |hash| Student.from_hash(hash) }
|
|
24
|
+
rescue JSON::ParserError
|
|
25
|
+
@students = []
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def save_to_file
|
|
30
|
+
return unless @file_path
|
|
31
|
+
|
|
32
|
+
data = @students.map(&:to_hash)
|
|
33
|
+
File.write(@file_path, JSON.pretty_generate(data))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def get_student_by_id(id)
|
|
37
|
+
@students.find { |student| student.id == id }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_k_n_student_short_list(k, n, existing_data_list = nil)
|
|
41
|
+
start_index = (n - 1) * k
|
|
42
|
+
selected = @students[start_index, k] || []
|
|
43
|
+
|
|
44
|
+
short_students = selected.map { |student| StudentShort.from_student(student) }
|
|
45
|
+
|
|
46
|
+
if existing_data_list && existing_data_list.is_a?(Data_list)
|
|
47
|
+
existing_data_list.data = short_students
|
|
48
|
+
existing_data_list
|
|
49
|
+
else
|
|
50
|
+
Data_list_student_short.new(short_students)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sort_by_full_name
|
|
55
|
+
@students.sort_by! { |student| student.last_name_initials.downcase }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def add_student(student)
|
|
59
|
+
new_id = @students.empty? ? 1 : @students.map(&:id).max + 1
|
|
60
|
+
student_with_id = Student.from_hash(student.to_hash.merge(id: new_id))
|
|
61
|
+
@students << student_with_id
|
|
62
|
+
student_with_id
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def replace_student_by_id(id, new_student)
|
|
66
|
+
index = @students.find_index { |s| s.id == id }
|
|
67
|
+
return false unless index
|
|
68
|
+
|
|
69
|
+
@students[index] = Student.from_hash(new_student.to_hash.merge(id: id))
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def delete_student_by_id(id)
|
|
74
|
+
size_before = @students.size
|
|
75
|
+
@students.reject! { |s| s.id == id }
|
|
76
|
+
size_before != @students.size
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def get_student_short_count
|
|
80
|
+
@students.size
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
attr_writer :students
|
|
86
|
+
end
|
data/lib/data_list.rb
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require_relative 'data_table'
|
|
2
|
+
require_relative 'student_short'
|
|
3
|
+
class Data_list
|
|
4
|
+
def initialize(data)
|
|
5
|
+
@data=data
|
|
6
|
+
@selected=[]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def select(index)
|
|
10
|
+
@selected<<@data[index]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def get_selected
|
|
14
|
+
@selected.map {|x| x.id}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def clear_selected
|
|
18
|
+
@selected.clear
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get_names
|
|
22
|
+
[*get_names_v, "last_name_initials", "contact", "git"]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_data
|
|
26
|
+
table_data = @data.each_with_index.map do |student, index|
|
|
27
|
+
[index + 1] + get_data_v(student)
|
|
28
|
+
end
|
|
29
|
+
Data_table.new(table_data)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def data=(data)
|
|
33
|
+
@data=data
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
def get_data_v(student)
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_names_v
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class Data_list_student_short < Data_list
|
|
48
|
+
private
|
|
49
|
+
def get_names_v
|
|
50
|
+
["№ по порядку"]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def get_data_v(student)
|
|
54
|
+
[
|
|
55
|
+
student.last_name_initials,
|
|
56
|
+
student.contact,
|
|
57
|
+
student.git
|
|
58
|
+
]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# students = [
|
|
65
|
+
# StudentShort.new(id: 1, last_name_initials: "K.K.", contact: "kosta2005kes@gmail.com", git: "git2"),
|
|
66
|
+
# StudentShort.new(id: 2, last_name_initials: "L.T.", contact: "krutfortnite@gmail.com", git: "git2"),
|
|
67
|
+
# StudentShort.new(id: 3, last_name_initials: "K.V.", contact: "magasiay@gmail.com", git: "git3")
|
|
68
|
+
# ]
|
|
69
|
+
# list = Data_list_student_short.new(students)
|
|
70
|
+
# list.select(0)
|
|
71
|
+
# list.select(2)
|
|
72
|
+
# table = list.get_data
|
|
73
|
+
# puts table.get(0, 0)
|
|
74
|
+
# puts table.get(1, 1)
|
|
75
|
+
# puts list.get_names
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative 'data_list'
|
|
2
|
+
require_relative 'student_short'
|
|
3
|
+
|
|
4
|
+
class DataListStudentShort < DataList
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
def column_names
|
|
8
|
+
["Фамилия И.О.", "Git", "Контакт"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def row_values(student_short)
|
|
12
|
+
[
|
|
13
|
+
student_short.last_name_initials || "",
|
|
14
|
+
student_short.git || "",
|
|
15
|
+
student_short.contact || ""
|
|
16
|
+
]
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/data_table.rb
ADDED
data/lib/student.rb
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
require_relative 'Base'
|
|
2
|
+
class Student<Base
|
|
3
|
+
REGULAR_PHONE = /\A(\+7|8)?[\s\-\(]?(\d{3})[\s\-\)]?\s*(\d{3})[\s\-]?(\d{2})[\s\-]?(\d{2})\z/
|
|
4
|
+
REGULAR_GIT = /\Ahttps:\/\/(github|gitlab)\.com\/[a-zA-Z0-9_-]+\z/
|
|
5
|
+
REGULAR_NAME = /\A[A-ZА-ЯЁ][a-zа-яё]+\z/
|
|
6
|
+
REGULAR_EMAIL = /\A[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\z/
|
|
7
|
+
REGULAR_TELEGRAM = /\A@[a-zA-Z0-9_]{5,32}\z/
|
|
8
|
+
include Comparable
|
|
9
|
+
attr_reader :first_name, :last_name, :patronymic
|
|
10
|
+
def initialize (last_name:, first_name:, patronymic: nil, id: nil, phone: nil, telegram: nil, email: nil, git: nil)
|
|
11
|
+
self.first_name= first_name
|
|
12
|
+
self.patronymic= patronymic
|
|
13
|
+
self.last_name= last_name
|
|
14
|
+
@id= id
|
|
15
|
+
self.contact= {:phone => phone, :email => email, :telegram => telegram}
|
|
16
|
+
self.git= git
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
def first_name=(value)
|
|
20
|
+
raise ArgumentError, "Неверное имя" unless self.class.valid_name?(value)
|
|
21
|
+
@first_name = value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def last_name=(value)
|
|
25
|
+
raise ArgumentError, "Неверная фамилия" unless self.class.valid_name?(value)
|
|
26
|
+
@last_name = value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def patronymic=(value)
|
|
30
|
+
raise ArgumentError, "Неверное отчество" unless self.class.valid_name?(value) if !value.nil?
|
|
31
|
+
@patronymic = value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def git=(value)
|
|
35
|
+
raise ArgumentError, "Неверный Git" unless self.class.valid_git?(value) if !value.nil?
|
|
36
|
+
@git = value
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def last_name_initials
|
|
40
|
+
string = "#{@last_name} #{@first_name[0]}."
|
|
41
|
+
if @patronymic != nil
|
|
42
|
+
return string + " #{@patronymic[0]}."
|
|
43
|
+
end
|
|
44
|
+
return string
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def contact
|
|
49
|
+
return "telegram - #{@telegram}" if @telegram
|
|
50
|
+
return "email - #{@email}" if @email
|
|
51
|
+
return "phone - #{@phone}" if @phone
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def contact=(contacts_hash)
|
|
56
|
+
contacts_hash.each do |type, value|
|
|
57
|
+
case type.to_sym
|
|
58
|
+
when :telegram
|
|
59
|
+
raise ArgumentError, "Неверный Telegram" unless self.class.valid_telegram?(value)
|
|
60
|
+
@telegram = value
|
|
61
|
+
when :email
|
|
62
|
+
raise ArgumentError, "Неверный email" unless self.class.valid_email?(value)
|
|
63
|
+
@email = value
|
|
64
|
+
when :phone
|
|
65
|
+
raise ArgumentError, "Неверный телефон" unless self.class.valid_phone?(value)
|
|
66
|
+
@phone = value
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_s
|
|
73
|
+
string = "Фамилия: #{@last_name}, Имя: #{@first_name}, Отчество: #{@patronymic.to_s} id: #{@id.to_s}, телефон: #{@phone.to_s}, телеграм: #{@telegram.to_s}, гит: #{@git.to_s}, почта: #{@email.to_s}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def has_contact?
|
|
77
|
+
@email!=nil || @phone!=nil || @telegram!=nil
|
|
78
|
+
end
|
|
79
|
+
def self.valid_git?(git)
|
|
80
|
+
!!(git =~ REGULAR_GIT) || git==nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.valid_telegram?(telegram)
|
|
84
|
+
!!(telegram =~ REGULAR_TELEGRAM) || telegram==nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.valid_phone?(phone)
|
|
88
|
+
!!(phone =~ REGULAR_PHONE) || phone==nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.valid_email?(email)
|
|
92
|
+
!!(email =~ REGULAR_EMAIL) || email==nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def self.valid_name?(name)
|
|
96
|
+
!!(name =~ REGULAR_NAME)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def <=>(other)
|
|
100
|
+
last_name_comparison = @last_name <=> other.last_name
|
|
101
|
+
return last_name_comparison unless last_name_comparison == 0
|
|
102
|
+
|
|
103
|
+
first_name_comparison = @first_name <=> other.first_name
|
|
104
|
+
return first_name_comparison unless first_name_comparison == 0
|
|
105
|
+
|
|
106
|
+
@patronymic.to_s <=> other.patronymic.to_s
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def ==(other)
|
|
111
|
+
return false unless other.is_a?(Base)
|
|
112
|
+
|
|
113
|
+
contacts_overlap = false
|
|
114
|
+
[@phone, @email, @telegram].each do |contact|
|
|
115
|
+
next if contact.nil? || contact.empty?
|
|
116
|
+
if [other.instance_variable_get(:@phone),
|
|
117
|
+
other.instance_variable_get(:@email),
|
|
118
|
+
other.instance_variable_get(:@telegram)].include?(contact)
|
|
119
|
+
contacts_overlap = true
|
|
120
|
+
break
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
comparison_key == other.comparison_key || contacts_overlap
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
alias eql? ==
|
|
128
|
+
|
|
129
|
+
def hash
|
|
130
|
+
comparison_key.hash
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def to_hash
|
|
134
|
+
{
|
|
135
|
+
id: @id,
|
|
136
|
+
first_name: @first_name,
|
|
137
|
+
last_name: @last_name,
|
|
138
|
+
patronymic: @patronymic,
|
|
139
|
+
git: @git,
|
|
140
|
+
phone: @phone,
|
|
141
|
+
telegram: @telegram,
|
|
142
|
+
email: @email
|
|
143
|
+
}
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def to_db_hash
|
|
147
|
+
{
|
|
148
|
+
first_name: @first_name,
|
|
149
|
+
last_name: @last_name,
|
|
150
|
+
patronymic: @patronymic,
|
|
151
|
+
git: @git,
|
|
152
|
+
phone: @phone,
|
|
153
|
+
telegram: @telegram,
|
|
154
|
+
email: @email
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
private
|
|
159
|
+
|
|
160
|
+
def fill_info_parts(info_parts)
|
|
161
|
+
info_parts << "Фамилия: #{last_name}"
|
|
162
|
+
info_parts << "Имя: #{first_name}"
|
|
163
|
+
info_parts << "Отчество: #{patronymic}" if patronymic
|
|
164
|
+
info_parts << "Телефон: #{@phone}" if @phone
|
|
165
|
+
info_parts << "Email: #{@email}" if @email
|
|
166
|
+
info_parts << "Telegram: #{@telegram}" if @telegram
|
|
167
|
+
info_parts << "Git: #{git}" if git
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def comparison_key
|
|
171
|
+
[last_name, first_name, patronymic].map { |n| n || '' }
|
|
172
|
+
end
|
|
173
|
+
def self.from_hash(hash)
|
|
174
|
+
new(
|
|
175
|
+
id: hash[:id],
|
|
176
|
+
last_name: hash[:last_name],
|
|
177
|
+
first_name: hash[:first_name],
|
|
178
|
+
patronymic: hash[:patronymic],
|
|
179
|
+
git: hash[:git],
|
|
180
|
+
phone: hash[:phone],
|
|
181
|
+
telegram: hash[:telegram],
|
|
182
|
+
email: hash[:email]
|
|
183
|
+
)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require_relative 'Base'
|
|
2
|
+
class StudentShort<Base
|
|
3
|
+
attr_reader :last_name_initials, :contact
|
|
4
|
+
def initialize (id:, last_name_initials:, contact:nil, git:nil)
|
|
5
|
+
@last_name_initials=last_name_initials
|
|
6
|
+
@id = id
|
|
7
|
+
@contact = contact
|
|
8
|
+
@git = git
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.from_student(student)
|
|
12
|
+
new(id: student.id, last_name_initials: student.last_name_initials, contact: student.contact, git: student.git)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_s
|
|
16
|
+
string = "id: #{@id.to_s}, ФИО: #{@last_name_initials}, гит: #{@git}, контакт: #{@contact}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def last_name_initials
|
|
20
|
+
@last_name_initials
|
|
21
|
+
end
|
|
22
|
+
def contact
|
|
23
|
+
@contact
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
require_relative "students_list_yaml/version"
|
|
5
|
+
require_relative "student"
|
|
6
|
+
require_relative "student_short"
|
|
7
|
+
require_relative "data_list"
|
|
8
|
+
require_relative "data_table"
|
|
9
|
+
require_relative "base"
|
|
10
|
+
|
|
11
|
+
module StudentsListYaml
|
|
12
|
+
class StudentsList
|
|
13
|
+
attr_reader :file_path
|
|
14
|
+
|
|
15
|
+
def initialize(file_path = nil)
|
|
16
|
+
@students = []
|
|
17
|
+
@file_path = file_path
|
|
18
|
+
load_data if file_path && File.exist?(file_path)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def load_data
|
|
22
|
+
return unless @file_path && File.exist?(@file_path)
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
file_content = File.read(@file_path)
|
|
26
|
+
return if file_content.strip.empty?
|
|
27
|
+
|
|
28
|
+
data = YAML.safe_load(file_content, symbolize_names: true)
|
|
29
|
+
@students = data.map { |student_data| Student.from_hash(student_data) }
|
|
30
|
+
rescue Psych::SyntaxError
|
|
31
|
+
@students = []
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def save_data
|
|
36
|
+
return unless @file_path
|
|
37
|
+
|
|
38
|
+
students_data = @students.map(&:to_hash)
|
|
39
|
+
File.write(@file_path, students_data.to_yaml)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_student_by_id(id)
|
|
43
|
+
@students.find { |student| student.id == id }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_k_n_student_short_list(k, n, existing_data_list = nil)
|
|
47
|
+
start_index = (n - 1) * k
|
|
48
|
+
selected_students = @students[start_index, k] || []
|
|
49
|
+
|
|
50
|
+
short_students = selected_students.map { |student| StudentShort.from_student(student) }
|
|
51
|
+
|
|
52
|
+
if existing_data_list && existing_data_list.is_a?(Data_list)
|
|
53
|
+
existing_data_list.data = short_students
|
|
54
|
+
existing_data_list
|
|
55
|
+
else
|
|
56
|
+
Data_list_student_short.new(short_students)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def sort_by_full_name
|
|
61
|
+
@students.sort_by! { |student| student.last_name_initials.downcase }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def add_student(student)
|
|
65
|
+
new_id = @students.empty? ? 1 : @students.map(&:id).max + 1
|
|
66
|
+
student_with_id = Student.from_hash(student.to_hash.merge(id: new_id))
|
|
67
|
+
@students << student_with_id
|
|
68
|
+
student_with_id
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def replace_student_by_id(id, new_student)
|
|
72
|
+
index = @students.find_index { |s| s.id == id }
|
|
73
|
+
return false unless index
|
|
74
|
+
|
|
75
|
+
@students[index] = Student.from_hash(new_student.to_hash.merge(id: id))
|
|
76
|
+
true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def delete_student_by_id(id)
|
|
80
|
+
initial_size = @students.size
|
|
81
|
+
@students.reject! { |s| s.id == id }
|
|
82
|
+
initial_size != @students.size
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def get_student_short_count
|
|
86
|
+
@students.size
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
attr_writer :students
|
|
92
|
+
end
|
|
93
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: students_list_yaml_Quartz
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kosta717
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rspec
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '3.12'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.12'
|
|
26
|
+
description: Класс для CRUD-операций со студентами и хранением в YAML-файле
|
|
27
|
+
email:
|
|
28
|
+
- kosta2005kes@gmail.com
|
|
29
|
+
executables: []
|
|
30
|
+
extensions: []
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
files:
|
|
33
|
+
- LICENSE.txt
|
|
34
|
+
- README.md
|
|
35
|
+
- lib/Base.rb
|
|
36
|
+
- lib/README.rdoc
|
|
37
|
+
- lib/Rakefile.rb
|
|
38
|
+
- lib/Students_list_JSON.rb
|
|
39
|
+
- lib/data_list.rb
|
|
40
|
+
- lib/data_list_Student_short.rb
|
|
41
|
+
- lib/data_table.rb
|
|
42
|
+
- lib/student.rb
|
|
43
|
+
- lib/student_short.rb
|
|
44
|
+
- lib/students_list_yaml.rb
|
|
45
|
+
- lib/students_list_yaml/version.rb
|
|
46
|
+
homepage: https://github.com/Kosta717/students_list_YAML
|
|
47
|
+
licenses:
|
|
48
|
+
- MIT
|
|
49
|
+
metadata:
|
|
50
|
+
homepage_uri: https://github.com/Kosta717/students_list_YAML
|
|
51
|
+
source_code_uri: https://github.com/Kosta717/students_list_YAML
|
|
52
|
+
rdoc_options: []
|
|
53
|
+
require_paths:
|
|
54
|
+
- lib
|
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '2.5'
|
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
|
+
requirements:
|
|
62
|
+
- - ">="
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '0'
|
|
65
|
+
requirements: []
|
|
66
|
+
rubygems_version: 4.0.3
|
|
67
|
+
specification_version: 4
|
|
68
|
+
summary: Управление списком студентов с сохранением в YAML
|
|
69
|
+
test_files: []
|