paper_trail_scrapbook 0.0.2
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/.codeclimate.yml +21 -0
- data/.rspec +5 -0
- data/.rubocop.yml +8 -0
- data/.ruby-gemset +1 -0
- data/Changelog.md +0 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +141 -0
- data/LICENSE.md +21 -0
- data/README.md +77 -0
- data/Rakefile +24 -0
- data/circle.yml +10 -0
- data/lib/paper_trail_scrapbook/changes.rb +89 -0
- data/lib/paper_trail_scrapbook/chapter.rb +49 -0
- data/lib/paper_trail_scrapbook/config.rb +13 -0
- data/lib/paper_trail_scrapbook/life_history.rb +17 -0
- data/lib/paper_trail_scrapbook/version.rb +4 -0
- data/lib/paper_trail_scrapbook.rb +51 -0
- data/paper_trail_scrapbook.gemspec +38 -0
- data/spec/dummy_app/Rakefile +7 -0
- data/spec/dummy_app/app/models/animal.rb +4 -0
- data/spec/dummy_app/app/models/article.rb +24 -0
- data/spec/dummy_app/app/models/authorship.rb +5 -0
- data/spec/dummy_app/app/models/bar_habtm.rb +4 -0
- data/spec/dummy_app/app/models/book.rb +9 -0
- data/spec/dummy_app/app/models/boolit.rb +4 -0
- data/spec/dummy_app/app/models/callback_modifier.rb +45 -0
- data/spec/dummy_app/app/models/car.rb +3 -0
- data/spec/dummy_app/app/models/cat.rb +2 -0
- data/spec/dummy_app/app/models/chapter.rb +9 -0
- data/spec/dummy_app/app/models/citation.rb +5 -0
- data/spec/dummy_app/app/models/custom_primary_key_record.rb +15 -0
- data/spec/dummy_app/app/models/customer.rb +4 -0
- data/spec/dummy_app/app/models/document.rb +6 -0
- data/spec/dummy_app/app/models/dog.rb +2 -0
- data/spec/dummy_app/app/models/editor.rb +4 -0
- data/spec/dummy_app/app/models/editorship.rb +5 -0
- data/spec/dummy_app/app/models/elephant.rb +3 -0
- data/spec/dummy_app/app/models/fluxor.rb +3 -0
- data/spec/dummy_app/app/models/foo_habtm.rb +5 -0
- data/spec/dummy_app/app/models/foo_widget.rb +2 -0
- data/spec/dummy_app/app/models/fruit.rb +5 -0
- data/spec/dummy_app/app/models/gadget.rb +3 -0
- data/spec/dummy_app/app/models/kitchen/banana.rb +5 -0
- data/spec/dummy_app/app/models/legacy_widget.rb +3 -0
- data/spec/dummy_app/app/models/line_item.rb +4 -0
- data/spec/dummy_app/app/models/not_on_update.rb +4 -0
- data/spec/dummy_app/app/models/on/create.rb +6 -0
- data/spec/dummy_app/app/models/on/destroy.rb +6 -0
- data/spec/dummy_app/app/models/on/empty_array.rb +6 -0
- data/spec/dummy_app/app/models/on/update.rb +6 -0
- data/spec/dummy_app/app/models/order.rb +5 -0
- data/spec/dummy_app/app/models/paragraph.rb +5 -0
- data/spec/dummy_app/app/models/person.rb +39 -0
- data/spec/dummy_app/app/models/post.rb +3 -0
- data/spec/dummy_app/app/models/post_with_status.rb +7 -0
- data/spec/dummy_app/app/models/quotation.rb +5 -0
- data/spec/dummy_app/app/models/section.rb +6 -0
- data/spec/dummy_app/app/models/skipper.rb +3 -0
- data/spec/dummy_app/app/models/song.rb +37 -0
- data/spec/dummy_app/app/models/thing.rb +3 -0
- data/spec/dummy_app/app/models/translation.rb +6 -0
- data/spec/dummy_app/app/models/truck.rb +4 -0
- data/spec/dummy_app/app/models/vehicle.rb +4 -0
- data/spec/dummy_app/app/models/whatchamajigger.rb +4 -0
- data/spec/dummy_app/app/models/widget.rb +8 -0
- data/spec/dummy_app/app/models/wotsit.rb +8 -0
- data/spec/dummy_app/app/versions/custom_primary_key_record_version.rb +3 -0
- data/spec/dummy_app/app/versions/joined_version.rb +6 -0
- data/spec/dummy_app/app/versions/json_version.rb +3 -0
- data/spec/dummy_app/app/versions/kitchen/banana_version.rb +5 -0
- data/spec/dummy_app/app/versions/post_version.rb +3 -0
- data/spec/dummy_app/config/application.rb +37 -0
- data/spec/dummy_app/config/boot.rb +24 -0
- data/spec/dummy_app/config/database.sqlite.yml +15 -0
- data/spec/dummy_app/config/database.yml +15 -0
- data/spec/dummy_app/config/environment.rb +5 -0
- data/spec/dummy_app/config/environments/development.rb +36 -0
- data/spec/dummy_app/config/environments/production.rb +74 -0
- data/spec/dummy_app/config/environments/test.rb +46 -0
- data/spec/dummy_app/config/initializers/backtrace_silencers.rb +9 -0
- data/spec/dummy_app/config/initializers/inflections.rb +10 -0
- data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
- data/spec/dummy_app/config/initializers/paper_trail.rb +1 -0
- data/spec/dummy_app/config/initializers/secret_token.rb +9 -0
- data/spec/dummy_app/config/initializers/session_store.rb +8 -0
- data/spec/dummy_app/config/locales/en.yml +5 -0
- data/spec/dummy_app/config/routes.rb +4 -0
- data/spec/dummy_app/config.ru +4 -0
- data/spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb +344 -0
- data/spec/dummy_app/db/schema.rb +296 -0
- data/spec/dummy_app/db/test.sqlite3 +0 -0
- data/spec/paper_trail_scrapbook/changes_spec.rb +6 -0
- data/spec/paper_trail_scrapbook/chapter_spec.rb +6 -0
- data/spec/paper_trail_scrapbook/config_spec.rb +17 -0
- data/spec/paper_trail_scrapbook/life_history_spec.rb +6 -0
- data/spec/paper_trail_scrapbook/version_spec.rb +6 -0
- data/spec/paper_trail_scrapbook_spec.rb +4 -0
- data/spec/spec_helper.rb +73 -0
- metadata +363 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 2227bf7cf82738d74887b11e4017a52950b5f774
|
|
4
|
+
data.tar.gz: 20465a690da01b2f9073059870e9e37e8ed3b0ee
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a50ecc1b54b77918bf1aed69156f6f0c7fe93ebba4bf3fe6c589a25f57ff6141af992679eb2128e5199e0013514a12b36bd235740c6f44c8c71233d82f23e1a8
|
|
7
|
+
data.tar.gz: 1b9d471bc89bd8f6f906aba1538d41c9727274add361110fb744d40b11c4072973b14f7beee2a815c6f62986f2217bf38597c54fd43ba262bd6226deb4d30cd9
|
data/.codeclimate.yml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
engines:
|
|
3
|
+
duplication:
|
|
4
|
+
enabled: true
|
|
5
|
+
config:
|
|
6
|
+
languages:
|
|
7
|
+
- ruby
|
|
8
|
+
fixme:
|
|
9
|
+
enabled: true
|
|
10
|
+
rubocop:
|
|
11
|
+
enabled: true
|
|
12
|
+
ratings:
|
|
13
|
+
paths:
|
|
14
|
+
- "**.inc"
|
|
15
|
+
- "**.js"
|
|
16
|
+
- "**.jsx"
|
|
17
|
+
- "**.module"
|
|
18
|
+
- "**.php"
|
|
19
|
+
- "**.py"
|
|
20
|
+
- "**.rb"
|
|
21
|
+
exclude_paths: []
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-gemset
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
paper_trail_scrapbook
|
data/Changelog.md
ADDED
|
File without changes
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
paper_trail_scrapbook (0.0.2)
|
|
5
|
+
activerecord (>= 4.0, < 5.2)
|
|
6
|
+
adamantium
|
|
7
|
+
concord
|
|
8
|
+
paper_trail
|
|
9
|
+
request_store (~> 1.1)
|
|
10
|
+
|
|
11
|
+
GEM
|
|
12
|
+
remote: http://rubygems.org/
|
|
13
|
+
specs:
|
|
14
|
+
actionpack (5.1.2)
|
|
15
|
+
actionview (= 5.1.2)
|
|
16
|
+
activesupport (= 5.1.2)
|
|
17
|
+
rack (~> 2.0)
|
|
18
|
+
rack-test (~> 0.6.3)
|
|
19
|
+
rails-dom-testing (~> 2.0)
|
|
20
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
|
21
|
+
actionview (5.1.2)
|
|
22
|
+
activesupport (= 5.1.2)
|
|
23
|
+
builder (~> 3.1)
|
|
24
|
+
erubi (~> 1.4)
|
|
25
|
+
rails-dom-testing (~> 2.0)
|
|
26
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
|
27
|
+
activemodel (5.1.2)
|
|
28
|
+
activesupport (= 5.1.2)
|
|
29
|
+
activerecord (5.1.2)
|
|
30
|
+
activemodel (= 5.1.2)
|
|
31
|
+
activesupport (= 5.1.2)
|
|
32
|
+
arel (~> 8.0)
|
|
33
|
+
activesupport (5.1.2)
|
|
34
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
35
|
+
i18n (~> 0.7)
|
|
36
|
+
minitest (~> 5.1)
|
|
37
|
+
tzinfo (~> 1.1)
|
|
38
|
+
adamantium (0.2.0)
|
|
39
|
+
ice_nine (~> 0.11.0)
|
|
40
|
+
memoizable (~> 0.4.0)
|
|
41
|
+
arel (8.0.0)
|
|
42
|
+
ast (2.3.0)
|
|
43
|
+
builder (3.2.3)
|
|
44
|
+
concord (0.1.5)
|
|
45
|
+
adamantium (~> 0.2.0)
|
|
46
|
+
equalizer (~> 0.0.9)
|
|
47
|
+
concurrent-ruby (1.0.5)
|
|
48
|
+
database_cleaner (1.6.1)
|
|
49
|
+
diff-lcs (1.3)
|
|
50
|
+
equalizer (0.0.11)
|
|
51
|
+
erubi (1.6.1)
|
|
52
|
+
ffaker (2.6.0)
|
|
53
|
+
i18n (0.8.4)
|
|
54
|
+
ice_nine (0.11.2)
|
|
55
|
+
loofah (2.0.3)
|
|
56
|
+
nokogiri (>= 1.5.9)
|
|
57
|
+
memoizable (0.4.2)
|
|
58
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
59
|
+
method_source (0.8.2)
|
|
60
|
+
mini_portile2 (2.2.0)
|
|
61
|
+
minitest (5.10.2)
|
|
62
|
+
nokogiri (1.8.0)
|
|
63
|
+
mini_portile2 (~> 2.2.0)
|
|
64
|
+
paper_trail (7.0.3)
|
|
65
|
+
activerecord (>= 4.0, < 5.2)
|
|
66
|
+
request_store (~> 1.1)
|
|
67
|
+
parallel (1.11.2)
|
|
68
|
+
parser (2.4.0.0)
|
|
69
|
+
ast (~> 2.2)
|
|
70
|
+
powerpack (0.1.1)
|
|
71
|
+
rack (2.0.3)
|
|
72
|
+
rack-test (0.6.3)
|
|
73
|
+
rack (>= 1.0)
|
|
74
|
+
rails-dom-testing (2.0.3)
|
|
75
|
+
activesupport (>= 4.2.0)
|
|
76
|
+
nokogiri (>= 1.6)
|
|
77
|
+
rails-html-sanitizer (1.0.3)
|
|
78
|
+
loofah (~> 2.0)
|
|
79
|
+
railties (5.1.2)
|
|
80
|
+
actionpack (= 5.1.2)
|
|
81
|
+
activesupport (= 5.1.2)
|
|
82
|
+
method_source
|
|
83
|
+
rake (>= 0.8.7)
|
|
84
|
+
thor (>= 0.18.1, < 2.0)
|
|
85
|
+
rainbow (2.2.2)
|
|
86
|
+
rake
|
|
87
|
+
rake (12.0.0)
|
|
88
|
+
request_store (1.3.2)
|
|
89
|
+
rspec-core (3.6.0)
|
|
90
|
+
rspec-support (~> 3.6.0)
|
|
91
|
+
rspec-expectations (3.6.0)
|
|
92
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
93
|
+
rspec-support (~> 3.6.0)
|
|
94
|
+
rspec-mocks (3.6.0)
|
|
95
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
96
|
+
rspec-support (~> 3.6.0)
|
|
97
|
+
rspec-rails (3.6.0)
|
|
98
|
+
actionpack (>= 3.0)
|
|
99
|
+
activesupport (>= 3.0)
|
|
100
|
+
railties (>= 3.0)
|
|
101
|
+
rspec-core (~> 3.6.0)
|
|
102
|
+
rspec-expectations (~> 3.6.0)
|
|
103
|
+
rspec-mocks (~> 3.6.0)
|
|
104
|
+
rspec-support (~> 3.6.0)
|
|
105
|
+
rspec-support (3.6.0)
|
|
106
|
+
rubocop (0.49.1)
|
|
107
|
+
parallel (~> 1.10)
|
|
108
|
+
parser (>= 2.3.3.1, < 3.0)
|
|
109
|
+
powerpack (~> 0.1)
|
|
110
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
111
|
+
ruby-progressbar (~> 1.7)
|
|
112
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
113
|
+
rubocop-rspec (1.15.1)
|
|
114
|
+
rubocop (>= 0.42.0)
|
|
115
|
+
ruby-progressbar (1.8.1)
|
|
116
|
+
sqlite3 (1.3.13)
|
|
117
|
+
thor (0.19.4)
|
|
118
|
+
thread_safe (0.3.6)
|
|
119
|
+
timecop (0.8.1)
|
|
120
|
+
tzinfo (1.2.3)
|
|
121
|
+
thread_safe (~> 0.1)
|
|
122
|
+
unicode-display_width (1.3.0)
|
|
123
|
+
|
|
124
|
+
PLATFORMS
|
|
125
|
+
ruby
|
|
126
|
+
|
|
127
|
+
DEPENDENCIES
|
|
128
|
+
database_cleaner (~> 1.2)
|
|
129
|
+
ffaker (~> 2.5)
|
|
130
|
+
paper_trail_scrapbook!
|
|
131
|
+
railties (>= 4.0, < 5.2)
|
|
132
|
+
rake (~> 12.0)
|
|
133
|
+
rspec-core (~> 3.6)
|
|
134
|
+
rspec-rails (~> 3.6)
|
|
135
|
+
rubocop
|
|
136
|
+
rubocop-rspec
|
|
137
|
+
sqlite3
|
|
138
|
+
timecop (~> 0.8.0)
|
|
139
|
+
|
|
140
|
+
BUNDLED WITH
|
|
141
|
+
1.15.1
|
data/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Tim Chambers
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Paper Trail Scrapbook
|
|
2
|
+
|
|
3
|
+
[](https://circleci.com/gh/tjchambers/paper_trail_scrapbook/tree/master)
|
|
4
|
+
|
|
5
|
+
Human Readable audit reporting for users of [PaperTrail](https://github.com/airblade/paper_trail) gem.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add PaperTrailScrapBook to your `Gemfile`.
|
|
10
|
+
|
|
11
|
+
`gem 'paper_trail_scrapbook'`
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
### Configuration
|
|
16
|
+
|
|
17
|
+
If you are using a ID of some sort to a class (i.e. _User_) for whodunnit in PaperTrail
|
|
18
|
+
then you should configure this into the scrapbook so it can locate and provide a human readable value for the whodunnit.
|
|
19
|
+
|
|
20
|
+
Create an initializer i.e. _config/initializers/paper_trail_scrapbook.rb
|
|
21
|
+
```ruby
|
|
22
|
+
PaperTrailScrapbook.config.whodunnit_class = User
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This gem will call `find` on that class, and translate the result to a
|
|
27
|
+
String via `to_s`, so it can be a simple Rails model, or a custom Ruby class that has `find` class method and
|
|
28
|
+
expects the `whodunnit` value. For example
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
class WhoDidIt
|
|
32
|
+
def self.find(email)
|
|
33
|
+
Person.find_by(email: email)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
PaperTrailScrapbook.config.whodunnit_class = WhoDidIt
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Life Story
|
|
43
|
+
```ruby
|
|
44
|
+
widget = Widget.find 42
|
|
45
|
+
|
|
46
|
+
text = PaperTrailScrapbook::LifeStory.new(widget).story
|
|
47
|
+
# On Wednesday, 07 Jun 2017 at 2:37 PM, Rob Owens created the following Widget information:
|
|
48
|
+
# • email: Tim@example.com
|
|
49
|
+
# • name: Tim's Widget
|
|
50
|
+
# • built: true
|
|
51
|
+
# • created_by: Rob Owens[1742]
|
|
52
|
+
# • provider: RedCharge[3113]
|
|
53
|
+
# • cost: 29612.0
|
|
54
|
+
# • discounted_price: 29612.0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Problems
|
|
58
|
+
|
|
59
|
+
Please use GitHub's [issue tracker](http://github.com/tjchambers/paper_trail_scrapbook/issues).
|
|
60
|
+
|
|
61
|
+
## Contributors
|
|
62
|
+
|
|
63
|
+
Created by Tim Chambers in 2017.
|
|
64
|
+
|
|
65
|
+
https://github.com/tjchambers/paper_trail_scrapbook/graphs/contributors
|
|
66
|
+
|
|
67
|
+
Acknowledgement and kudos to Andy Stewart, Ben Atkins, Jared Beck, and all the other contributors to the PaperTrail gem.
|
|
68
|
+
Without them this would not be possible.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## Intellectual Property
|
|
72
|
+
|
|
73
|
+
Copyright (c) 2017 Tim Chambers (tim@possibilogy.com).
|
|
74
|
+
Released under the MIT licence.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
Bundler::GemHelper.install_tasks
|
|
3
|
+
|
|
4
|
+
desc 'Set a relevant database.yml for testing'
|
|
5
|
+
task :prepare do
|
|
6
|
+
ENV['DB'] ||= 'sqlite'
|
|
7
|
+
FileUtils.cp(
|
|
8
|
+
"spec/dummy_app/config/database.#{ENV['DB']}.yml",
|
|
9
|
+
'spec/dummy_app/config/database.yml'
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require 'rspec/core/rake_task'
|
|
14
|
+
desc 'Run tests on PaperTrailScrapbook with RSpec'
|
|
15
|
+
task(:spec).clear
|
|
16
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
17
|
+
t.verbose = false # hide list of specs bit.ly/1nVq3Jn
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
require 'rubocop/rake_task'
|
|
21
|
+
RuboCop::RakeTask.new
|
|
22
|
+
|
|
23
|
+
desc 'Default: run all available test suites'
|
|
24
|
+
task default: %i[rubocop prepare spec]
|
data/circle.yml
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module PaperTrailScrapbook
|
|
2
|
+
class Changes
|
|
3
|
+
include Concord.new(:version)
|
|
4
|
+
|
|
5
|
+
def initialize(*)
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
build_associations
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
BULLET = ' •'.freeze
|
|
12
|
+
|
|
13
|
+
def change_log
|
|
14
|
+
changes.map { |k, v| digest(k, v) }.compact.join("\n").gsub('_id:', ':')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def digest(k, v)
|
|
20
|
+
old, new = v
|
|
21
|
+
return if old.nil? && (new.nil? || new.eql?(''))
|
|
22
|
+
|
|
23
|
+
"#{BULLET} #{k}: " + if creating?
|
|
24
|
+
find_value(k, new).to_s
|
|
25
|
+
elsif old.nil?
|
|
26
|
+
"#{find_value(k, new)} added"
|
|
27
|
+
elsif new.nil?
|
|
28
|
+
"#{find_value(k, old)} was *removed*"
|
|
29
|
+
else
|
|
30
|
+
"#{find_value(k, old)} -> #{find_value(k, new)}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def creating?
|
|
35
|
+
version.event.eql?('create')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def find_value(key, value)
|
|
39
|
+
return value.to_s unless assoc.key?(key)
|
|
40
|
+
|
|
41
|
+
return '*empty*' unless value
|
|
42
|
+
|
|
43
|
+
begin
|
|
44
|
+
assoc[key].find(value).to_s + "[#{value}]"
|
|
45
|
+
rescue
|
|
46
|
+
"*not found*[#{value}]"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def assoc_klass(name, options = {})
|
|
51
|
+
direct_class = options[:class_name]
|
|
52
|
+
return direct_class if direct_class && !direct_class.is_a?(String)
|
|
53
|
+
|
|
54
|
+
Object.const_get((direct_class || name.to_s).classify)
|
|
55
|
+
rescue
|
|
56
|
+
Object.const_set(name.to_s.classify, Class.new)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def klass
|
|
60
|
+
assoc_klass(version.item_type)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def build_associations
|
|
64
|
+
@assoc ||=
|
|
65
|
+
Hash[
|
|
66
|
+
klass
|
|
67
|
+
.reflect_on_all_associations
|
|
68
|
+
.select { |a| a.macro.equal?(:belongs_to) }
|
|
69
|
+
.map { |x| [x.foreign_key.to_s, assoc_klass(x.name, x.options)] }
|
|
70
|
+
]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def object_changes
|
|
74
|
+
version.object_changes
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def changes
|
|
78
|
+
@chs ||= if object_changes
|
|
79
|
+
YAML
|
|
80
|
+
.load(object_changes)
|
|
81
|
+
.except('updated_at', 'created_at ', 'id')
|
|
82
|
+
else
|
|
83
|
+
{}
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
attr_reader :assoc, :chs
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module PaperTrailScrapbook
|
|
2
|
+
class Chapter
|
|
3
|
+
include Concord.new(:version)
|
|
4
|
+
|
|
5
|
+
UNKNOWN = '*the app*'.freeze
|
|
6
|
+
|
|
7
|
+
def story
|
|
8
|
+
"On #{whenn}, #{who} #{kind} the following #{model} information:".split.join(' ') + "\n#{changes}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def model
|
|
14
|
+
version.item_type
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def changes
|
|
18
|
+
PaperTrailScrapbook::Changes.new(version).change_log
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def who
|
|
22
|
+
author = version.version_author
|
|
23
|
+
if author
|
|
24
|
+
if PaperTrailScrapbook.whodunnit_class
|
|
25
|
+
PaperTrailScrapbook.whodunnit_class.find(author.to_i).to_s
|
|
26
|
+
else
|
|
27
|
+
author
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
UNKNOWN
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def whenn
|
|
35
|
+
version.created_at.strftime('%A, %d %b %Y at %l:%M %p')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def kind
|
|
39
|
+
case version.event
|
|
40
|
+
when 'create'
|
|
41
|
+
'created'
|
|
42
|
+
when 'update'
|
|
43
|
+
'updated'
|
|
44
|
+
when 'destroy'
|
|
45
|
+
'destroyed'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
|
|
3
|
+
module PaperTrailScrapbook
|
|
4
|
+
# Global configuration affecting all threads.
|
|
5
|
+
class Config
|
|
6
|
+
include Singleton
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
# Variables which affect all threads, whose access is synchronized.
|
|
10
|
+
@mutex = Mutex.new
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module PaperTrailScrapbook
|
|
2
|
+
class LifeHistory
|
|
3
|
+
def initialize(object)
|
|
4
|
+
@versions = object.versions
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def story
|
|
8
|
+
versions.map do |v|
|
|
9
|
+
Chapter.new(v).story
|
|
10
|
+
end.join("\n\n")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
attr_reader :versions
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'adamantium'
|
|
2
|
+
require 'concord'
|
|
3
|
+
require 'digest/sha1'
|
|
4
|
+
require 'equalizer'
|
|
5
|
+
require 'ice_nine'
|
|
6
|
+
require 'pathname'
|
|
7
|
+
require 'paper_trail_scrapbook/config'
|
|
8
|
+
require 'paper_trail_scrapbook/chapter'
|
|
9
|
+
require 'paper_trail_scrapbook/changes'
|
|
10
|
+
require 'paper_trail_scrapbook/life_history'
|
|
11
|
+
require 'paper_trail_scrapbook/version'
|
|
12
|
+
|
|
13
|
+
# Library namespace
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
module PaperTrailScrapbook
|
|
17
|
+
class << self
|
|
18
|
+
# Sets class associated with PaperTrail.whodunnit
|
|
19
|
+
# @api public
|
|
20
|
+
def whodunnit_class=(value)
|
|
21
|
+
paper_trail_scrapbook_store[:whodunnit_class] = value
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# class responsible for any changes that occur.
|
|
25
|
+
#
|
|
26
|
+
# @api public
|
|
27
|
+
def whodunnit_class
|
|
28
|
+
paper_trail_scrapbook_store[:whodunnit_class]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Thread-safe hash to hold PaperTrailScrapbook's data. Initializing with needed
|
|
32
|
+
# default values.
|
|
33
|
+
# @api private
|
|
34
|
+
def paper_trail_scrapbook_store
|
|
35
|
+
RequestStore.store[:paper_trail_scrapbook] ||= {}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns PaperTrailScrapbook's configuration object.
|
|
39
|
+
# @api private
|
|
40
|
+
def config
|
|
41
|
+
@config ||= PaperTrailScrapbook::Config.instance
|
|
42
|
+
yield @config if block_given?
|
|
43
|
+
@config
|
|
44
|
+
end
|
|
45
|
+
alias configure config
|
|
46
|
+
|
|
47
|
+
def version
|
|
48
|
+
VERSION::STRING
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require File.expand_path('../lib/paper_trail_scrapbook/version', __FILE__)
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |gem|
|
|
4
|
+
gem.name = 'paper_trail_scrapbook'
|
|
5
|
+
gem.version = PaperTrailScrapbook::VERSION.dup
|
|
6
|
+
gem.date = Time.now.utc.strftime('%Y-%m-%d')
|
|
7
|
+
gem.summary = 'Paper Trail Scrapbook'
|
|
8
|
+
gem.description = "Human Readable Change Log for Paper Trail'd data"
|
|
9
|
+
gem.authors = ['Timothy Chambers']
|
|
10
|
+
gem.email = 'tim@possibilogy.com'
|
|
11
|
+
gem.files = `git ls-files`.split("\n")
|
|
12
|
+
gem.homepage = 'https://github.com/tjchambers/paper_trail_scrapbook'
|
|
13
|
+
gem.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
gem.required_rubygems_version = '>= 1.3.6'
|
|
16
|
+
gem.required_ruby_version = '>= 2.2.0'
|
|
17
|
+
|
|
18
|
+
# Rails does not follow semver, makes breaking changes in minor versions.
|
|
19
|
+
gem.add_dependency 'activerecord', ['>= 4.0', '< 5.2']
|
|
20
|
+
gem.add_dependency 'request_store', '~> 1.1'
|
|
21
|
+
gem.add_dependency 'adamantium'
|
|
22
|
+
gem.add_dependency 'concord'
|
|
23
|
+
gem.add_dependency 'paper_trail'
|
|
24
|
+
|
|
25
|
+
gem.add_development_dependency 'rake', '~> 12.0'
|
|
26
|
+
gem.add_development_dependency 'ffaker', '~> 2.5'
|
|
27
|
+
|
|
28
|
+
# Why `railties`? Possibly used by `spec/dummy_app` boot up?
|
|
29
|
+
gem.add_development_dependency 'railties', ['>= 4.0', '< 5.2']
|
|
30
|
+
|
|
31
|
+
gem.add_development_dependency 'rspec-rails', '~> 3.6'
|
|
32
|
+
gem.add_development_dependency 'rspec-core', '~> 3.6'
|
|
33
|
+
gem.add_development_dependency 'database_cleaner', '~> 1.2'
|
|
34
|
+
gem.add_development_dependency 'rubocop'
|
|
35
|
+
gem.add_development_dependency 'rubocop-rspec'
|
|
36
|
+
gem.add_development_dependency 'timecop', '~> 0.8.0'
|
|
37
|
+
gem.add_development_dependency 'sqlite3'
|
|
38
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
3
|
+
|
|
4
|
+
require File.expand_path('../config/application', __FILE__)
|
|
5
|
+
require 'rake'
|
|
6
|
+
|
|
7
|
+
Dummy::Application.load_tasks
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Article < ActiveRecord::Base
|
|
2
|
+
has_paper_trail(
|
|
3
|
+
ignore: [
|
|
4
|
+
:title, {
|
|
5
|
+
abstract: proc { |obj|
|
|
6
|
+
['ignore abstract', 'Other abstract'].include? obj.abstract
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
only: [:content, { abstract: proc { |obj| obj.abstract.present? } }],
|
|
11
|
+
skip: [:file_upload],
|
|
12
|
+
meta: {
|
|
13
|
+
answer: 42,
|
|
14
|
+
action: :action_data_provider_method,
|
|
15
|
+
question: proc { "31 + 11 = #{31 + 11}" },
|
|
16
|
+
article_id: proc { |article| article.id },
|
|
17
|
+
title: :title
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def action_data_provider_method
|
|
22
|
+
object_id.to_s
|
|
23
|
+
end
|
|
24
|
+
end
|