audited-serialize 0.0.1 → 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.
- checksums.yaml +4 -4
- data/README.md +53 -1
- data/lib/audited/audit_extensions.rb +25 -0
- data/lib/audited/serialization.rb +80 -0
- data/lib/audited/serialization_changes/array_module.rb +22 -0
- data/lib/audited/serialization_changes/boolean_module.rb +23 -0
- data/lib/audited/serialization_changes/common_module.rb +23 -0
- data/lib/audited/serialization_changes/date_module.rb +29 -0
- data/lib/audited/serialization_changes/datetime_module.rb +29 -0
- data/lib/audited/serialization_changes/enum_module.rb +22 -0
- data/lib/audited/serialization_changes/object_module.rb +29 -0
- data/lib/audited/serialization_changes/related_record_module.rb +47 -0
- data/lib/audited-serialize.rb +1 -1
- data/lib/audited_config.rb +11 -0
- data/lib/audited_serialize.rb +3 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49e601e7c12bb7e67d5763e08d8dda00f8ddab573ceb4d58a8ca7f399e88e507
|
4
|
+
data.tar.gz: 6c69689f1e0ab5ebe8ad474b62cb62ee1d6f5c9350629376974b04bd2615f9a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1b9db4eabd0f067f330abbbb8322d1fe30d78b98cea86607c318b03363538c3748b88cab47c231911f42afd0f6a3c1454a6fc9901149c26a9d94aafe173f798
|
7
|
+
data.tar.gz: '0965e44d1a5415d488514b6dccefc0bea10961b299391572359f8b0f60abb7fec434599e1f439036f58fd299c3ebdf2bb452199f00a7b0836914cd05649bd5f8'
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Audited Serialize
|
2
|
+
[](https://badge.fury.io/rb/audited-serialize)
|
2
3
|
|
3
|
-
Гем для сериализации аудит-логов на базе Audited
|
4
|
+
Гем для сериализации аудит-логов на базе Audited.
|
4
5
|
|
5
6
|
## Установка
|
6
7
|
|
@@ -15,3 +16,54 @@ gem 'audited-serialize'
|
|
15
16
|
```
|
16
17
|
bundle
|
17
18
|
```
|
19
|
+
|
20
|
+
## Использование
|
21
|
+
|
22
|
+
Для вызова сериализованного списка изменений вызовите метод `.changes_list` на экземпляре audit-класса (по умолчанию - `Audited::Audit`)
|
23
|
+
|
24
|
+
```
|
25
|
+
audit = Audited::Audit.first
|
26
|
+
audit.changes_list
|
27
|
+
```
|
28
|
+
|
29
|
+
## Заголовки связанных записей
|
30
|
+
|
31
|
+
При наличии в аудит-логах полей, содержащих ID связанных сущностей, по умолчанию будет отображено название (поле `name`) этой сущности. При отсутствии у сущности поля `name` или необходимости отображения значения другого поля можно задать название этого поля в модели
|
32
|
+
|
33
|
+
```
|
34
|
+
# app/models/user.rb
|
35
|
+
|
36
|
+
class User < ApplicationRecord
|
37
|
+
|
38
|
+
audit title: :email
|
39
|
+
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
## Конфигурация
|
44
|
+
|
45
|
+
Изменение настроек сериализации осуществляется путем редактирования стандартного файла конфигурации `Audited`
|
46
|
+
|
47
|
+
```
|
48
|
+
# config/initializers/audited.rb
|
49
|
+
|
50
|
+
Audited.config do |config|
|
51
|
+
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
## Исключения
|
56
|
+
|
57
|
+
Для добавления исключений для полей сущностей, которые не будут отображаться в списке добавьте в конфиг `serialization_exceptions`.
|
58
|
+
|
59
|
+
```
|
60
|
+
# config/initializers/audited.rb
|
61
|
+
|
62
|
+
Audited.config do |config|
|
63
|
+
|
64
|
+
config.serialization_exceptions = {
|
65
|
+
'User' => ['role']
|
66
|
+
}
|
67
|
+
|
68
|
+
end
|
69
|
+
```
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'audited/serialization'
|
2
|
+
require 'audited/serialization_changes/array_module'
|
3
|
+
require 'audited/serialization_changes/boolean_module'
|
4
|
+
require 'audited/serialization_changes/common_module'
|
5
|
+
require 'audited/serialization_changes/date_module'
|
6
|
+
require 'audited/serialization_changes/datetime_module'
|
7
|
+
require 'audited/serialization_changes/enum_module'
|
8
|
+
require 'audited/serialization_changes/object_module'
|
9
|
+
require 'audited/serialization_changes/related_record_module'
|
10
|
+
|
11
|
+
module Audited
|
12
|
+
class Audit < ::ActiveRecord::Base
|
13
|
+
|
14
|
+
include Audited::Serialization
|
15
|
+
include Audited::SerializationChanges::ArrayModule
|
16
|
+
include Audited::SerializationChanges::BooleanModule
|
17
|
+
include Audited::SerializationChanges::CommonModule
|
18
|
+
include Audited::SerializationChanges::DateModule
|
19
|
+
include Audited::SerializationChanges::DatetimeModule
|
20
|
+
include Audited::SerializationChanges::EnumModule
|
21
|
+
include Audited::SerializationChanges::ObjectModule
|
22
|
+
include Audited::SerializationChanges::RelatedRecordModule
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Audited
|
2
|
+
module Serialization
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def changes_list
|
7
|
+
# проверка на наличие модели
|
8
|
+
# в случае ее отсутствия, верятнее всего она была удалена
|
9
|
+
begin
|
10
|
+
model = auditable_type.constantize
|
11
|
+
rescue NameError
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
columns_hash = model.columns_hash
|
16
|
+
@reflections = model_reflections(model)
|
17
|
+
|
18
|
+
audited_changes.map do |column, value|
|
19
|
+
# пропускаем, если колонка в списке исключений
|
20
|
+
next if Audited.serialization_exceptions[auditable_type]&.include?(column)
|
21
|
+
|
22
|
+
@column = column
|
23
|
+
@db_column = columns_hash[column]
|
24
|
+
|
25
|
+
# пропускаем, если колонка теперь отсутствует в БД
|
26
|
+
next unless @db_column
|
27
|
+
|
28
|
+
# русскоязычное название поля
|
29
|
+
field = password_changes? ? 'Пароль' : @db_column.comment
|
30
|
+
|
31
|
+
if action == 'update' && value.is_a?(Array)
|
32
|
+
# значения, измененные во время редактирования
|
33
|
+
@initial, @changed = value
|
34
|
+
else
|
35
|
+
# значения, заданные во время создания
|
36
|
+
@changed = value
|
37
|
+
end
|
38
|
+
|
39
|
+
# определение изменений было/стало
|
40
|
+
from, to = changes_from_to
|
41
|
+
|
42
|
+
# пропускаем, если изменения не зафиксированы
|
43
|
+
next if from.blank? && to.blank?
|
44
|
+
|
45
|
+
{
|
46
|
+
field:, from:, to:
|
47
|
+
}
|
48
|
+
end.compact
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def model_reflections(model)
|
54
|
+
model.reflections.to_h { |_rel, reflection| [reflection.foreign_key, reflection.klass] }
|
55
|
+
end
|
56
|
+
|
57
|
+
def changes_from_to
|
58
|
+
if related_record_changes?
|
59
|
+
related_record_changes
|
60
|
+
elsif object_changes?
|
61
|
+
object_changes
|
62
|
+
elsif array_changes?
|
63
|
+
array_changes
|
64
|
+
elsif password_changes?
|
65
|
+
password_changes
|
66
|
+
elsif date_changes?
|
67
|
+
date_changes
|
68
|
+
elsif datetime_changes?
|
69
|
+
datetime_changes
|
70
|
+
elsif boolean_changes?
|
71
|
+
boolean_changes
|
72
|
+
elsif enum_changes?
|
73
|
+
enum_changes
|
74
|
+
else
|
75
|
+
common_column_changes
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module ArrayModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def array_changes?
|
10
|
+
@initial.is_a?(Array) || @changed.is_a?(Array)
|
11
|
+
end
|
12
|
+
|
13
|
+
def array_changes
|
14
|
+
from = @initial&.join(', ')
|
15
|
+
to = @changed&.join(', ')
|
16
|
+
|
17
|
+
return from, to
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module BooleanModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def boolean_changes?
|
10
|
+
classes = [TrueClass, FalseClass]
|
11
|
+
|
12
|
+
classes.include?(@initial.class) || classes.include?(@changed.class)
|
13
|
+
end
|
14
|
+
|
15
|
+
def boolean_changes
|
16
|
+
values = { true => 'Да', false => 'Нет' }
|
17
|
+
|
18
|
+
return values[@initial], values[@changed]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module CommonModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def password_changes?
|
10
|
+
@column == 'encrypted_password'
|
11
|
+
end
|
12
|
+
|
13
|
+
def password_changes
|
14
|
+
return nil, '<новый>'
|
15
|
+
end
|
16
|
+
|
17
|
+
def common_column_changes
|
18
|
+
return @initial, @changed
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module DateModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def date_changes?
|
10
|
+
@initial&.to_date&.acts_like?(:date) && @initial.to_s.include?('-') && @initial.to_s.exclude?(':') rescue false
|
11
|
+
@changed&.to_date&.acts_like?(:date) && @changed.to_s.include?('-') && @changed.to_s.exclude?(':') rescue false
|
12
|
+
end
|
13
|
+
|
14
|
+
def date_changes
|
15
|
+
from = date_change_formatted(@initial)
|
16
|
+
to = date_change_formatted(@changed)
|
17
|
+
|
18
|
+
return from, to
|
19
|
+
end
|
20
|
+
|
21
|
+
def date_change_formatted(value)
|
22
|
+
return if value.blank?
|
23
|
+
|
24
|
+
Date.parse(value).strftime('%d.%m.%Y')
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module DatetimeModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def datetime_changes?
|
10
|
+
@initial&.to_date&.acts_like?(:date) && @initial.include?(':') rescue false
|
11
|
+
@changed&.to_date&.acts_like?(:date) && @changed.include?(':') rescue false
|
12
|
+
end
|
13
|
+
|
14
|
+
def datetime_changes
|
15
|
+
from = datetime_change_formatted(@initial)
|
16
|
+
to = datetime_change_formatted(@changed)
|
17
|
+
|
18
|
+
return from, to
|
19
|
+
end
|
20
|
+
|
21
|
+
def datetime_change_formatted(value)
|
22
|
+
return if value.blank?
|
23
|
+
|
24
|
+
DateTime.parse(value).in_time_zone('Europe/Moscow').strftime('%d.%m.%Y %H:%M')
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module EnumModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def enum_changes?
|
10
|
+
@db_column.type == :enum
|
11
|
+
end
|
12
|
+
|
13
|
+
def enum_changes
|
14
|
+
type = @db_column.sql_type
|
15
|
+
values = I18n.t("enums.#{type}").stringify_keys
|
16
|
+
|
17
|
+
return values[@initial], values[@changed]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module ObjectModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def object_changes?
|
10
|
+
@initial.is_a?(Hash) || @changed.is_a?(Hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
def object_changes
|
14
|
+
from = object_change_formatted(@initial, @changed)
|
15
|
+
to = object_change_formatted(@changed, @initial)
|
16
|
+
|
17
|
+
return from, to
|
18
|
+
end
|
19
|
+
|
20
|
+
def object_change_formatted(from, to)
|
21
|
+
# удаление дубликатов ключей/значений
|
22
|
+
hash = (from.to_a - to.to_a).to_h
|
23
|
+
|
24
|
+
hash.map { |key, val| "#{key.humanize}: #{val}" }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Audited
|
2
|
+
module SerializationChanges
|
3
|
+
module RelatedRecordModule
|
4
|
+
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def related_record_changes?
|
10
|
+
@reflections[@column].present?
|
11
|
+
end
|
12
|
+
|
13
|
+
def related_record_changes
|
14
|
+
# модель связанной сущности от колонки
|
15
|
+
related_model = @reflections[@column]
|
16
|
+
|
17
|
+
# заданные/измененные значения
|
18
|
+
from = related_record_value(related_model, @initial)
|
19
|
+
to = related_record_value(related_model, @changed)
|
20
|
+
|
21
|
+
return from, to
|
22
|
+
end
|
23
|
+
|
24
|
+
def related_record_value(related_model, related_record_id)
|
25
|
+
return '' unless related_record_id
|
26
|
+
|
27
|
+
record = related_model.find_by(id: related_record_id)
|
28
|
+
return "Запись ##{related_record_id}" unless record
|
29
|
+
|
30
|
+
related_record_auditing_title(record)
|
31
|
+
end
|
32
|
+
|
33
|
+
def related_record_auditing_title(record)
|
34
|
+
audited_title = record.class.audited_options[:title]
|
35
|
+
|
36
|
+
if audited_title
|
37
|
+
record.send(audited_title)
|
38
|
+
elsif record.class.column_names.include?('name')
|
39
|
+
record.name
|
40
|
+
else
|
41
|
+
"##{record.id}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/audited-serialize.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'audited_serialize'
|
1
|
+
require 'audited_serialize'
|
data/lib/audited_serialize.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: audited-serialize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Павел Бабин
|
@@ -32,6 +32,17 @@ extra_rdoc_files: []
|
|
32
32
|
files:
|
33
33
|
- README.md
|
34
34
|
- lib/audited-serialize.rb
|
35
|
+
- lib/audited/audit_extensions.rb
|
36
|
+
- lib/audited/serialization.rb
|
37
|
+
- lib/audited/serialization_changes/array_module.rb
|
38
|
+
- lib/audited/serialization_changes/boolean_module.rb
|
39
|
+
- lib/audited/serialization_changes/common_module.rb
|
40
|
+
- lib/audited/serialization_changes/date_module.rb
|
41
|
+
- lib/audited/serialization_changes/datetime_module.rb
|
42
|
+
- lib/audited/serialization_changes/enum_module.rb
|
43
|
+
- lib/audited/serialization_changes/object_module.rb
|
44
|
+
- lib/audited/serialization_changes/related_record_module.rb
|
45
|
+
- lib/audited_config.rb
|
35
46
|
- lib/audited_serialize.rb
|
36
47
|
homepage:
|
37
48
|
licenses:
|
@@ -53,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
64
|
- !ruby/object:Gem::Version
|
54
65
|
version: '0'
|
55
66
|
requirements: []
|
56
|
-
rubygems_version: 3.
|
67
|
+
rubygems_version: 3.4.10
|
57
68
|
signing_key:
|
58
69
|
specification_version: 4
|
59
70
|
summary: Сериализация аудит-логов Audited
|