audited-serialize 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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