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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d48590492cd52769b859d9fe98d28d8bdaffa3ba106cf31c600799d3302efa2b
4
- data.tar.gz: 98c8038df1e219d2162bfd4cedb6b5bf2a6fe74abbf1dbb0c987673cb36f1239
3
+ metadata.gz: 49e601e7c12bb7e67d5763e08d8dda00f8ddab573ceb4d58a8ca7f399e88e507
4
+ data.tar.gz: 6c69689f1e0ab5ebe8ad474b62cb62ee1d6f5c9350629376974b04bd2615f9a2
5
5
  SHA512:
6
- metadata.gz: 6a90a9a8bbc607becefdaa2441d94916970af899cb20cbe694c7d24db6cca6fbf1f78de0fedf376baaad2b220fb6eed634ddb8a04ec515afb06aea055de7838f
7
- data.tar.gz: 4552d6ee7304c6e0561144f27ea1ec32b9b9647be8822b268179956d91295e3b872026f217a2fe33a0a670958412de0681704ff8e61f3d7fa1a0048fdc724beb
6
+ metadata.gz: d1b9db4eabd0f067f330abbbb8322d1fe30d78b98cea86607c318b03363538c3748b88cab47c231911f42afd0f6a3c1454a6fc9901149c26a9d94aafe173f798
7
+ data.tar.gz: '0965e44d1a5415d488514b6dccefc0bea10961b299391572359f8b0f60abb7fec434599e1f439036f58fd299c3ebdf2bb452199f00a7b0836914cd05649bd5f8'
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Audited Serialize
2
+ [![Gem Version](https://badge.fury.io/rb/audited-serialize.svg)](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
@@ -1 +1 @@
1
- require 'audited_serialize'
1
+ require 'audited_serialize'
@@ -0,0 +1,11 @@
1
+ module Audited
2
+
3
+ class << self
4
+
5
+ attr_accessor :serialization_exceptions
6
+
7
+ end
8
+
9
+ @serialization_exceptions = {}
10
+
11
+ end
@@ -1,2 +1,5 @@
1
+ require 'audited_config'
2
+ require 'audited/audit_extensions'
3
+
1
4
  module AuditedSerialize
2
5
  end
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.1
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.0.6
67
+ rubygems_version: 3.4.10
57
68
  signing_key:
58
69
  specification_version: 4
59
70
  summary: Сериализация аудит-логов Audited