paper_trail-human 0.3.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/CHANGELOG.md +52 -0
- data/LICENSE.txt +21 -0
- data/README.md +435 -0
- data/config/locales/en.yml +6 -0
- data/config/locales/pt-BR.yml +6 -0
- data/lib/generators/paper_trail/human/install_generator.rb +17 -0
- data/lib/generators/paper_trail/human/templates/initializer.rb +23 -0
- data/lib/paper_trail/human/adapters/formatters/html.rb +44 -0
- data/lib/paper_trail/human/adapters/formatters/markdown.rb +32 -0
- data/lib/paper_trail/human/adapters/formatters/text.rb +33 -0
- data/lib/paper_trail/human/adapters/resolvers/boolean.rb +22 -0
- data/lib/paper_trail/human/adapters/resolvers/custom.rb +21 -0
- data/lib/paper_trail/human/adapters/resolvers/date.rb +36 -0
- data/lib/paper_trail/human/adapters/resolvers/enum.rb +57 -0
- data/lib/paper_trail/human/adapters/resolvers/number.rb +62 -0
- data/lib/paper_trail/human/adapters/resolvers/relation.rb +41 -0
- data/lib/paper_trail/human/adapters/resolvers/text.rb +29 -0
- data/lib/paper_trail/human/configuration.rb +88 -0
- data/lib/paper_trail/human/core/batch_presenter.rb +133 -0
- data/lib/paper_trail/human/core/change_extractor.rb +79 -0
- data/lib/paper_trail/human/core/event_translator.rb +25 -0
- data/lib/paper_trail/human/core/field_formatter.rb +92 -0
- data/lib/paper_trail/human/core/presenter.rb +76 -0
- data/lib/paper_trail/human/core/timeline.rb +30 -0
- data/lib/paper_trail/human/ports/resolver.rb +13 -0
- data/lib/paper_trail/human/railtie.rb +26 -0
- data/lib/paper_trail/human/version.rb +7 -0
- data/lib/paper_trail/human.rb +74 -0
- data/lib/paper_trail-human.rb +5 -0
- metadata +100 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PaperTrail
|
|
4
|
+
module Human
|
|
5
|
+
module Core
|
|
6
|
+
class Presenter
|
|
7
|
+
def initialize(configuration)
|
|
8
|
+
@configuration = configuration
|
|
9
|
+
@change_extractor = ChangeExtractor.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(version, only: nil, except: nil)
|
|
13
|
+
changes = @change_extractor.call(version)
|
|
14
|
+
model_config = @configuration.config_for(version.item_type)
|
|
15
|
+
formatter = FieldFormatter.new(
|
|
16
|
+
model_config,
|
|
17
|
+
version.item_type,
|
|
18
|
+
field_name_resolver: @configuration.field_name_resolver
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
result = {
|
|
22
|
+
user: @configuration.resolve_whodunnit(version.whodunnit),
|
|
23
|
+
event: EventTranslator.call(version.event, translate: @configuration.translate_events),
|
|
24
|
+
model: version.item_type,
|
|
25
|
+
item_id: version.item_id,
|
|
26
|
+
created_at: version.created_at,
|
|
27
|
+
fields: build_fields(changes, formatter, version.event, only: only, except: except)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
item_name = @configuration.resolve_item_name(version)
|
|
31
|
+
result[:item_name] = item_name if item_name
|
|
32
|
+
|
|
33
|
+
apply_after_format(result, version)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def build_fields(changes, formatter, event, only: nil, except: nil)
|
|
39
|
+
changes
|
|
40
|
+
.reject { |field, _| @configuration.ignored_fields.include?(field.to_s) }
|
|
41
|
+
.select { |field, _| filter_field?(field, only, except) }
|
|
42
|
+
.map { |field, values| format_field(formatter, field, values, event) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def filter_field?(field, only, except)
|
|
46
|
+
field_s = field.to_s
|
|
47
|
+
return only.map(&:to_s).include?(field_s) if only
|
|
48
|
+
|
|
49
|
+
return !except.map(&:to_s).include?(field_s) if except
|
|
50
|
+
|
|
51
|
+
true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def format_field(formatter, field, values, event)
|
|
55
|
+
previous_value, new_value = Array(values)
|
|
56
|
+
result = formatter.call(field, previous_value, new_value)
|
|
57
|
+
|
|
58
|
+
case event
|
|
59
|
+
when 'create'
|
|
60
|
+
result.delete(:previous_value)
|
|
61
|
+
when 'destroy'
|
|
62
|
+
result.delete(:value)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
result
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def apply_after_format(result, version)
|
|
69
|
+
return result unless @configuration.after_format
|
|
70
|
+
|
|
71
|
+
@configuration.after_format.call(result, version)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PaperTrail
|
|
4
|
+
module Human
|
|
5
|
+
module Core
|
|
6
|
+
class Timeline
|
|
7
|
+
GROUPINGS = {
|
|
8
|
+
day: '%Y-%m-%d',
|
|
9
|
+
week: '%G-W%V',
|
|
10
|
+
month: '%Y-%m',
|
|
11
|
+
year: '%Y'
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
def initialize(configuration)
|
|
15
|
+
@configuration = configuration
|
|
16
|
+
@batch_presenter = BatchPresenter.new(configuration)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def call(versions, group_by: :day, only: nil, except: nil)
|
|
20
|
+
formatted = @batch_presenter.call(versions, only: only, except: except)
|
|
21
|
+
format_str = GROUPINGS.fetch(group_by.to_sym) do
|
|
22
|
+
raise Error, "Unknown group_by: #{group_by}. Available: #{GROUPINGS.keys.join(', ')}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
formatted.group_by { |r| r[:created_at].strftime(format_str) }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PaperTrail
|
|
4
|
+
module Human
|
|
5
|
+
class Railtie < ::Rails::Railtie
|
|
6
|
+
initializer 'paper_trail_human.i18n' do
|
|
7
|
+
locale_path = File.expand_path('../../../config/locales/*.yml', __dir__)
|
|
8
|
+
I18n.load_path += Dir[locale_path]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
initializer 'paper_trail_human.extend_version_model' do
|
|
12
|
+
ActiveSupport.on_load(:active_record) do
|
|
13
|
+
if PaperTrail::Human.configuration.extend_version_model
|
|
14
|
+
PaperTrail::Version.include(PaperTrail::Human::VersionExtension)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module VersionExtension
|
|
21
|
+
def formatted_log
|
|
22
|
+
PaperTrail::Human.format(self)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'human/version'
|
|
4
|
+
require_relative 'human/configuration'
|
|
5
|
+
require_relative 'human/core/change_extractor'
|
|
6
|
+
require_relative 'human/core/field_formatter'
|
|
7
|
+
require_relative 'human/core/event_translator'
|
|
8
|
+
require_relative 'human/core/presenter'
|
|
9
|
+
require_relative 'human/core/batch_presenter'
|
|
10
|
+
require_relative 'human/core/timeline'
|
|
11
|
+
require_relative 'human/ports/resolver'
|
|
12
|
+
require_relative 'human/adapters/resolvers/relation'
|
|
13
|
+
require_relative 'human/adapters/resolvers/enum'
|
|
14
|
+
require_relative 'human/adapters/resolvers/boolean'
|
|
15
|
+
require_relative 'human/adapters/resolvers/custom'
|
|
16
|
+
require_relative 'human/adapters/resolvers/text'
|
|
17
|
+
require_relative 'human/adapters/resolvers/date'
|
|
18
|
+
require_relative 'human/adapters/resolvers/number'
|
|
19
|
+
require_relative 'human/adapters/formatters/text'
|
|
20
|
+
require_relative 'human/adapters/formatters/markdown'
|
|
21
|
+
require_relative 'human/adapters/formatters/html'
|
|
22
|
+
|
|
23
|
+
module PaperTrail
|
|
24
|
+
module Human
|
|
25
|
+
class Error < StandardError; end
|
|
26
|
+
|
|
27
|
+
MUTEX = Mutex.new
|
|
28
|
+
private_constant :MUTEX
|
|
29
|
+
|
|
30
|
+
FORMATTERS = {
|
|
31
|
+
text: Adapters::Formatters::Text,
|
|
32
|
+
markdown: Adapters::Formatters::Markdown,
|
|
33
|
+
html: Adapters::Formatters::Html
|
|
34
|
+
}.freeze
|
|
35
|
+
private_constant :FORMATTERS
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
def configuration
|
|
39
|
+
@configuration || MUTEX.synchronize { @configuration ||= Configuration.new }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def configure
|
|
43
|
+
yield(configuration)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def reset_configuration!
|
|
47
|
+
MUTEX.synchronize { @configuration = Configuration.new }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def format(version, only: nil, except: nil, as: nil)
|
|
51
|
+
result = Core::Presenter.new(configuration).call(version, only: only, except: except)
|
|
52
|
+
as ? formatter(as).call(result) : result
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def format_collection(versions, only: nil, except: nil, as: nil)
|
|
56
|
+
results = Core::BatchPresenter.new(configuration).call(versions, only: only, except: except)
|
|
57
|
+
as ? results.map { |r| formatter(as).call(r) } : results
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def formatter(type)
|
|
63
|
+
klass = FORMATTERS[type.to_sym]
|
|
64
|
+
raise Error, "Unknown format: #{type}. Available: #{FORMATTERS.keys.join(', ')}" unless klass
|
|
65
|
+
|
|
66
|
+
klass.new
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def timeline(versions, group_by: :day, only: nil, except: nil)
|
|
70
|
+
Core::Timeline.new(configuration).call(versions, group_by: group_by, only: only, except: except)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: paper_trail-human
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gabriel
|
|
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: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '6.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '6.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: paper_trail
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '12.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '12.0'
|
|
40
|
+
description: Resolves foreign keys, enums, booleans and custom transformations from
|
|
41
|
+
PaperTrail::Version into structured, UI-ready hashes.
|
|
42
|
+
executables: []
|
|
43
|
+
extensions: []
|
|
44
|
+
extra_rdoc_files: []
|
|
45
|
+
files:
|
|
46
|
+
- CHANGELOG.md
|
|
47
|
+
- LICENSE.txt
|
|
48
|
+
- README.md
|
|
49
|
+
- config/locales/en.yml
|
|
50
|
+
- config/locales/pt-BR.yml
|
|
51
|
+
- lib/generators/paper_trail/human/install_generator.rb
|
|
52
|
+
- lib/generators/paper_trail/human/templates/initializer.rb
|
|
53
|
+
- lib/paper_trail-human.rb
|
|
54
|
+
- lib/paper_trail/human.rb
|
|
55
|
+
- lib/paper_trail/human/adapters/formatters/html.rb
|
|
56
|
+
- lib/paper_trail/human/adapters/formatters/markdown.rb
|
|
57
|
+
- lib/paper_trail/human/adapters/formatters/text.rb
|
|
58
|
+
- lib/paper_trail/human/adapters/resolvers/boolean.rb
|
|
59
|
+
- lib/paper_trail/human/adapters/resolvers/custom.rb
|
|
60
|
+
- lib/paper_trail/human/adapters/resolvers/date.rb
|
|
61
|
+
- lib/paper_trail/human/adapters/resolvers/enum.rb
|
|
62
|
+
- lib/paper_trail/human/adapters/resolvers/number.rb
|
|
63
|
+
- lib/paper_trail/human/adapters/resolvers/relation.rb
|
|
64
|
+
- lib/paper_trail/human/adapters/resolvers/text.rb
|
|
65
|
+
- lib/paper_trail/human/configuration.rb
|
|
66
|
+
- lib/paper_trail/human/core/batch_presenter.rb
|
|
67
|
+
- lib/paper_trail/human/core/change_extractor.rb
|
|
68
|
+
- lib/paper_trail/human/core/event_translator.rb
|
|
69
|
+
- lib/paper_trail/human/core/field_formatter.rb
|
|
70
|
+
- lib/paper_trail/human/core/presenter.rb
|
|
71
|
+
- lib/paper_trail/human/core/timeline.rb
|
|
72
|
+
- lib/paper_trail/human/ports/resolver.rb
|
|
73
|
+
- lib/paper_trail/human/railtie.rb
|
|
74
|
+
- lib/paper_trail/human/version.rb
|
|
75
|
+
homepage: https://github.com/gabrielrumiranda/paper_trail-human
|
|
76
|
+
licenses:
|
|
77
|
+
- MIT
|
|
78
|
+
metadata:
|
|
79
|
+
homepage_uri: https://github.com/gabrielrumiranda/paper_trail-human
|
|
80
|
+
source_code_uri: https://github.com/gabrielrumiranda/paper_trail-human
|
|
81
|
+
changelog_uri: https://github.com/gabrielrumiranda/paper_trail-human/blob/main/CHANGELOG.md
|
|
82
|
+
rubygems_mfa_required: 'true'
|
|
83
|
+
rdoc_options: []
|
|
84
|
+
require_paths:
|
|
85
|
+
- lib
|
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - ">="
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '3.1'
|
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
requirements: []
|
|
97
|
+
rubygems_version: 3.6.8
|
|
98
|
+
specification_version: 4
|
|
99
|
+
summary: Transforms PaperTrail versions into human-readable hashes for audit logs.
|
|
100
|
+
test_files: []
|