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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +21 -0
  3. data/.rspec +5 -0
  4. data/.rubocop.yml +8 -0
  5. data/.ruby-gemset +1 -0
  6. data/Changelog.md +0 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +141 -0
  9. data/LICENSE.md +21 -0
  10. data/README.md +77 -0
  11. data/Rakefile +24 -0
  12. data/circle.yml +10 -0
  13. data/lib/paper_trail_scrapbook/changes.rb +89 -0
  14. data/lib/paper_trail_scrapbook/chapter.rb +49 -0
  15. data/lib/paper_trail_scrapbook/config.rb +13 -0
  16. data/lib/paper_trail_scrapbook/life_history.rb +17 -0
  17. data/lib/paper_trail_scrapbook/version.rb +4 -0
  18. data/lib/paper_trail_scrapbook.rb +51 -0
  19. data/paper_trail_scrapbook.gemspec +38 -0
  20. data/spec/dummy_app/Rakefile +7 -0
  21. data/spec/dummy_app/app/models/animal.rb +4 -0
  22. data/spec/dummy_app/app/models/article.rb +24 -0
  23. data/spec/dummy_app/app/models/authorship.rb +5 -0
  24. data/spec/dummy_app/app/models/bar_habtm.rb +4 -0
  25. data/spec/dummy_app/app/models/book.rb +9 -0
  26. data/spec/dummy_app/app/models/boolit.rb +4 -0
  27. data/spec/dummy_app/app/models/callback_modifier.rb +45 -0
  28. data/spec/dummy_app/app/models/car.rb +3 -0
  29. data/spec/dummy_app/app/models/cat.rb +2 -0
  30. data/spec/dummy_app/app/models/chapter.rb +9 -0
  31. data/spec/dummy_app/app/models/citation.rb +5 -0
  32. data/spec/dummy_app/app/models/custom_primary_key_record.rb +15 -0
  33. data/spec/dummy_app/app/models/customer.rb +4 -0
  34. data/spec/dummy_app/app/models/document.rb +6 -0
  35. data/spec/dummy_app/app/models/dog.rb +2 -0
  36. data/spec/dummy_app/app/models/editor.rb +4 -0
  37. data/spec/dummy_app/app/models/editorship.rb +5 -0
  38. data/spec/dummy_app/app/models/elephant.rb +3 -0
  39. data/spec/dummy_app/app/models/fluxor.rb +3 -0
  40. data/spec/dummy_app/app/models/foo_habtm.rb +5 -0
  41. data/spec/dummy_app/app/models/foo_widget.rb +2 -0
  42. data/spec/dummy_app/app/models/fruit.rb +5 -0
  43. data/spec/dummy_app/app/models/gadget.rb +3 -0
  44. data/spec/dummy_app/app/models/kitchen/banana.rb +5 -0
  45. data/spec/dummy_app/app/models/legacy_widget.rb +3 -0
  46. data/spec/dummy_app/app/models/line_item.rb +4 -0
  47. data/spec/dummy_app/app/models/not_on_update.rb +4 -0
  48. data/spec/dummy_app/app/models/on/create.rb +6 -0
  49. data/spec/dummy_app/app/models/on/destroy.rb +6 -0
  50. data/spec/dummy_app/app/models/on/empty_array.rb +6 -0
  51. data/spec/dummy_app/app/models/on/update.rb +6 -0
  52. data/spec/dummy_app/app/models/order.rb +5 -0
  53. data/spec/dummy_app/app/models/paragraph.rb +5 -0
  54. data/spec/dummy_app/app/models/person.rb +39 -0
  55. data/spec/dummy_app/app/models/post.rb +3 -0
  56. data/spec/dummy_app/app/models/post_with_status.rb +7 -0
  57. data/spec/dummy_app/app/models/quotation.rb +5 -0
  58. data/spec/dummy_app/app/models/section.rb +6 -0
  59. data/spec/dummy_app/app/models/skipper.rb +3 -0
  60. data/spec/dummy_app/app/models/song.rb +37 -0
  61. data/spec/dummy_app/app/models/thing.rb +3 -0
  62. data/spec/dummy_app/app/models/translation.rb +6 -0
  63. data/spec/dummy_app/app/models/truck.rb +4 -0
  64. data/spec/dummy_app/app/models/vehicle.rb +4 -0
  65. data/spec/dummy_app/app/models/whatchamajigger.rb +4 -0
  66. data/spec/dummy_app/app/models/widget.rb +8 -0
  67. data/spec/dummy_app/app/models/wotsit.rb +8 -0
  68. data/spec/dummy_app/app/versions/custom_primary_key_record_version.rb +3 -0
  69. data/spec/dummy_app/app/versions/joined_version.rb +6 -0
  70. data/spec/dummy_app/app/versions/json_version.rb +3 -0
  71. data/spec/dummy_app/app/versions/kitchen/banana_version.rb +5 -0
  72. data/spec/dummy_app/app/versions/post_version.rb +3 -0
  73. data/spec/dummy_app/config/application.rb +37 -0
  74. data/spec/dummy_app/config/boot.rb +24 -0
  75. data/spec/dummy_app/config/database.sqlite.yml +15 -0
  76. data/spec/dummy_app/config/database.yml +15 -0
  77. data/spec/dummy_app/config/environment.rb +5 -0
  78. data/spec/dummy_app/config/environments/development.rb +36 -0
  79. data/spec/dummy_app/config/environments/production.rb +74 -0
  80. data/spec/dummy_app/config/environments/test.rb +46 -0
  81. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +9 -0
  82. data/spec/dummy_app/config/initializers/inflections.rb +10 -0
  83. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  84. data/spec/dummy_app/config/initializers/paper_trail.rb +1 -0
  85. data/spec/dummy_app/config/initializers/secret_token.rb +9 -0
  86. data/spec/dummy_app/config/initializers/session_store.rb +8 -0
  87. data/spec/dummy_app/config/locales/en.yml +5 -0
  88. data/spec/dummy_app/config/routes.rb +4 -0
  89. data/spec/dummy_app/config.ru +4 -0
  90. data/spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb +344 -0
  91. data/spec/dummy_app/db/schema.rb +296 -0
  92. data/spec/dummy_app/db/test.sqlite3 +0 -0
  93. data/spec/paper_trail_scrapbook/changes_spec.rb +6 -0
  94. data/spec/paper_trail_scrapbook/chapter_spec.rb +6 -0
  95. data/spec/paper_trail_scrapbook/config_spec.rb +17 -0
  96. data/spec/paper_trail_scrapbook/life_history_spec.rb +6 -0
  97. data/spec/paper_trail_scrapbook/version_spec.rb +6 -0
  98. data/spec/paper_trail_scrapbook_spec.rb +4 -0
  99. data/spec/spec_helper.rb +73 -0
  100. 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
@@ -0,0 +1,5 @@
1
+ --color
2
+ --require spec_helper
3
+ --format progress
4
+ --warnings
5
+ --order random
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ AllCops:
2
+ DisabledByDefault: false
3
+ TargetRubyVersion: 2.2
4
+ TargetRailsVersion: 4.0
5
+ DisplayCopNames: true
6
+
7
+ Security/YAMLLoad:
8
+ Enabled: false
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ paper_trail_scrapbook
data/Changelog.md ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec # DRY! No need to repeat the gem deps here
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
+ [![CircleCI](https://circleci.com/gh/tjchambers/paper_trail_scrapbook/tree/master.svg?style=svg)](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,10 @@
1
+ ---
2
+ machine:
3
+ ruby:
4
+ version: '2.2.7'
5
+ dependencies:
6
+ pre:
7
+ - gem install bundler
8
+ test:
9
+ override:
10
+ - bundle exec rake spec
@@ -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,4 @@
1
+ module PaperTrailScrapbook
2
+ # Current version
3
+ VERSION = '0.0.2'.freeze
4
+ 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,4 @@
1
+ class Animal < ActiveRecord::Base
2
+ has_paper_trail
3
+ self.inheritance_column = 'species'
4
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ class Authorship < ActiveRecord::Base
2
+ belongs_to :book
3
+ belongs_to :author, class_name: 'Person'
4
+ has_paper_trail
5
+ end
@@ -0,0 +1,4 @@
1
+ class BarHabtm < ActiveRecord::Base
2
+ has_and_belongs_to_many :foo_habtms
3
+ has_paper_trail
4
+ end
@@ -0,0 +1,9 @@
1
+ class Book < ActiveRecord::Base
2
+ has_many :authorships, dependent: :destroy
3
+ has_many :authors, through: :authorships
4
+
5
+ has_many :editorships, dependent: :destroy
6
+ has_many :editors, through: :editorships
7
+
8
+ has_paper_trail
9
+ end
@@ -0,0 +1,4 @@
1
+ class Boolit < ActiveRecord::Base
2
+ default_scope { where(scoped: true) }
3
+ has_paper_trail
4
+ end