paper_trail_scrapbook 0.1.13 → 0.1.19

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
  SHA1:
3
- metadata.gz: 6c453ce85bdc41cc81c5f1d9f16922ae23c3936d
4
- data.tar.gz: dc47a13264e5bb62434b4e8cd169c78e607b7842
3
+ metadata.gz: edc42760ad65ddabf5e4b5cbe6078a2106e05fd3
4
+ data.tar.gz: f414b720536a35971713cd2ab6615665861be9f0
5
5
  SHA512:
6
- metadata.gz: 1848ed2409a099393b9adf26975d2b35575f742fe18b4d9a8af22108739102ab58aa663b9c28f68f38b7f16a9f007d4c1c759071fcb7b49d9126817d47f23d79
7
- data.tar.gz: 7d9e1dbbf17832aa1e95b82f97efbf4d70d2596f4652b9d88256a56a2fcdb573b5a000236e333522193262681931ee34b8333f060d9be5c1fa143f7e15f265b9
6
+ metadata.gz: db255b9d214220f0161e76d0cc748b5a315be057fded74adfbaa4b79aa58403791196283381074050d0a3cb3fcc49b667ee57662268f6835c47b5b651c8f75cc
7
+ data.tar.gz: f05cfe2ca064ace2658641863635d640bf425cee52d5c57b9a14f51f63d849e2572f06b056468f175be867056a51891b95fab38545dc38974d1543cf7e2e42f9
@@ -1,6 +1,8 @@
1
1
  defaults: &defaults
2
2
  docker:
3
3
  - image: circleci/ruby:2.5.0-node-browsers
4
+ environment:
5
+ PGUSER: circleci
4
6
  - image: circleci/postgres:9.5-alpine
5
7
  environment:
6
8
  POSTGRES_USER: circleci
@@ -21,10 +23,11 @@ jobs:
21
23
  command: |
22
24
  echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
23
25
  source $BASH_ENV
24
- gem install bundler
26
+ gem install bundler -v $BUNDLER_VERSION
25
27
  - run:
26
28
  name: Bundle Install
27
- command: bundle check || bundle install
29
+ command:
30
+ bundle check || bundle install
28
31
  - save_cache:
29
32
  key: paper_trail_scrapbook-{{ checksum "Gemfile.lock" }}
30
33
  paths:
@@ -1,36 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- paper_trail_scrapbook (0.1.13)
4
+ paper_trail_scrapbook (0.1.19)
5
5
  activerecord
6
6
  adamantium
7
7
  concord
8
- paper_trail (>= 5.2, <= 9.2.0)
8
+ paper_trail (>= 5.2, <= 10.2.1)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
13
  abstract_type (0.0.7)
14
- actionpack (5.2.2.1)
15
- actionview (= 5.2.2.1)
16
- activesupport (= 5.2.2.1)
14
+ actionpack (5.2.3)
15
+ actionview (= 5.2.3)
16
+ activesupport (= 5.2.3)
17
17
  rack (~> 2.0)
18
18
  rack-test (>= 0.6.3)
19
19
  rails-dom-testing (~> 2.0)
20
20
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
21
- actionview (5.2.2.1)
22
- activesupport (= 5.2.2.1)
21
+ actionview (5.2.3)
22
+ activesupport (= 5.2.3)
23
23
  builder (~> 3.1)
24
24
  erubi (~> 1.4)
25
25
  rails-dom-testing (~> 2.0)
26
26
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
27
- activemodel (5.2.2.1)
28
- activesupport (= 5.2.2.1)
29
- activerecord (5.2.2.1)
30
- activemodel (= 5.2.2.1)
31
- activesupport (= 5.2.2.1)
27
+ activemodel (5.2.3)
28
+ activesupport (= 5.2.3)
29
+ activerecord (5.2.3)
30
+ activemodel (= 5.2.3)
31
+ activesupport (= 5.2.3)
32
32
  arel (>= 9.0)
33
- activesupport (5.2.2.1)
33
+ activesupport (5.2.3)
34
34
  concurrent-ruby (~> 1.0, >= 1.0.2)
35
35
  i18n (>= 0.7, < 2)
36
36
  minitest (~> 5.1)
@@ -51,25 +51,25 @@ GEM
51
51
  adamantium (~> 0.2.0)
52
52
  equalizer (~> 0.0.9)
53
53
  concurrent-ruby (1.1.5)
54
- crass (1.0.4)
54
+ crass (1.0.5)
55
55
  database_cleaner (1.6.2)
56
56
  diff-lcs (1.3)
57
57
  docile (1.1.5)
58
58
  equalizer (0.0.11)
59
- erubi (1.8.0)
59
+ erubi (1.9.0)
60
60
  ffaker (2.8.1)
61
- i18n (1.6.0)
61
+ i18n (1.7.0)
62
62
  concurrent-ruby (~> 1.0)
63
63
  ice_nine (0.11.2)
64
- json (2.1.0)
65
- loofah (2.2.3)
64
+ json (2.3.1)
65
+ loofah (2.3.1)
66
66
  crass (~> 1.0.2)
67
67
  nokogiri (>= 1.5.9)
68
68
  memoizable (0.4.2)
69
69
  thread_safe (~> 0.3, >= 0.3.1)
70
70
  method_source (0.9.2)
71
71
  mini_portile2 (2.4.0)
72
- minitest (5.11.3)
72
+ minitest (5.12.2)
73
73
  morpher (0.2.6)
74
74
  abstract_type (~> 0.0.7)
75
75
  adamantium (~> 0.2.0)
@@ -98,43 +98,42 @@ GEM
98
98
  mutant-rspec (0.8.14)
99
99
  mutant (~> 0.8.14)
100
100
  rspec-core (>= 3.4.0, < 3.7.0)
101
- nokogiri (1.10.2)
101
+ nokogiri (1.10.8)
102
102
  mini_portile2 (~> 2.4.0)
103
- paper_trail (9.2.0)
104
- activerecord (>= 4.2, < 5.3)
105
- paper_trail-association_tracking (< 2)
103
+ paper_trail (10.2.1)
104
+ activerecord (>= 4.2, < 6.1)
106
105
  request_store (~> 1.1)
107
- paper_trail-association_tracking (1.1.1)
108
106
  parallel (1.12.1)
109
107
  parser (2.4.0.2)
110
108
  ast (~> 2.3)
111
109
  pg (0.18.4)
112
110
  powerpack (0.1.1)
113
111
  procto (0.0.3)
114
- rack (2.0.6)
112
+ rack (2.2.3)
115
113
  rack-test (1.1.0)
116
114
  rack (>= 1.0, < 3)
117
115
  rails-dom-testing (2.0.3)
118
116
  activesupport (>= 4.2.0)
119
117
  nokogiri (>= 1.6)
120
- rails-html-sanitizer (1.0.4)
118
+ rails-html-sanitizer (1.2.0)
121
119
  loofah (~> 2.2, >= 2.2.2)
122
- railties (5.2.2.1)
123
- actionpack (= 5.2.2.1)
124
- activesupport (= 5.2.2.1)
120
+ railties (5.2.3)
121
+ actionpack (= 5.2.3)
122
+ activesupport (= 5.2.3)
125
123
  method_source
126
124
  rake (>= 0.8.7)
127
125
  thor (>= 0.19.0, < 2.0)
128
126
  rainbow (3.0.0)
129
- rake (10.4.2)
127
+ rake (13.0.1)
130
128
  regexp_parser (0.4.9)
131
- request_store (1.4.1)
129
+ request_store (1.5.0)
132
130
  rack (>= 1.4)
133
131
  rspec-core (3.6.0)
134
132
  rspec-support (~> 3.6.0)
135
133
  rspec-expectations (3.6.0)
136
134
  diff-lcs (>= 1.2.0, < 2.0)
137
135
  rspec-support (~> 3.6.0)
136
+ rspec-jumpstart (1.1.2)
138
137
  rspec-mocks (3.6.0)
139
138
  diff-lcs (>= 1.2.0, < 2.0)
140
139
  rspec-support (~> 3.6.0)
@@ -181,19 +180,21 @@ GEM
181
180
 
182
181
  PLATFORMS
183
182
  ruby
183
+ x86_64-darwin-20
184
184
 
185
185
  DEPENDENCIES
186
186
  codeclimate-test-reporter (~> 1.0.7)
187
187
  database_cleaner (~> 1.2)
188
188
  ffaker (~> 2.5)
189
- loofah (~> 2.2.3)
189
+ loofah (~> 2.3.1)
190
190
  mutant
191
191
  mutant-rspec
192
192
  paper_trail_scrapbook!
193
193
  pg (= 0.18.4)
194
194
  rack (>= 2.0.6)
195
- railties (= 5.2.2.1)
196
- rake (~> 10.4.2)
195
+ railties (= 5.2.3)
196
+ rake (~> 13.0.1)
197
+ rspec-jumpstart
197
198
  rspec-rails
198
199
  rspec_junit_formatter
199
200
  rubocop
@@ -202,4 +203,4 @@ DEPENDENCIES
202
203
  timecop (~> 0.8.0)
203
204
 
204
205
  BUNDLED WITH
205
- 2.0.1
206
+ 2.2.2
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Paper Trail Scrapbook
2
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)
3
+ [![CircleCI](https://circleci.com/gh/hintmedia/paper_trail_scrapbook/tree/master.svg?style=svg)](https://circleci.com/gh/tjchambers/paper_trail_scrapbook/tree/master)
4
4
  [![Gem Version](https://badge.fury.io/rb/paper_trail_scrapbook.svg)](https://badge.fury.io/rb/paper_trail_scrapbook)
5
5
 
6
6
  Human Readable audit reporting for users of [PaperTrail](https://github.com/paper-trail-gem/paper_trail) gem.
@@ -16,9 +16,9 @@ Add PaperTrailScrapBook to your `Gemfile`.
16
16
  ### Configuration
17
17
 
18
18
  This gem is dependent on [PaperTrail](https://github.com/paper-trail-gem/paper_trail),
19
- and specifically, on the `object_changes` column in the `PaperTrail::Version`
19
+ and specifically, on the `object_changes` column in the `PaperTrail::Version`
20
20
  table. If your `PaperTrail` installation does not include this column, you can
21
- add it manually, or re-runthe `PaperTrail` generator:
21
+ add it manually, or re-run the `PaperTrail` generator:
22
22
 
23
23
  ```
24
24
  bundle exec rake generate paper_trail:install --with_changes
@@ -60,6 +60,14 @@ end
60
60
  PaperTrailScrapbook.config.whodunnit_class = WhoDidIt
61
61
  ```
62
62
 
63
+ You also have the option of seeing the most recent changes first (default is chronological)
64
+
65
+ ```ruby
66
+
67
+ config.recent_first = true
68
+
69
+ ```
70
+
63
71
  ### Life Story
64
72
 
65
73
  The `LifeStory` module provides a complete history of an object (limited by the
@@ -70,12 +78,12 @@ widget = Widget.find 42
70
78
  text = PaperTrailScrapbook::LifeHistory.new(widget).story
71
79
  # On Wednesday, 07 Jun 2017 at 2:37 PM, Rob Owens created the following Widget information:
72
80
  # • email: Tim@example.com
73
- # • name: Tim's Widget
81
+ # • name: Tim's Widget
74
82
  # • built: true
75
83
  # • created_by: Rob Owens[1742]
76
84
  # • provider: RedCharge[3113]
77
85
  # • cost: 29612.0
78
- # • discounted_price: 29612.0
86
+ # • discounted_price: 29612.0
79
87
  ```
80
88
 
81
89
  If desired, you can implement a `trailed_related_content` method in your model
@@ -110,18 +118,64 @@ text = PaperTrailScrapbook::LifeHistory.new(widget).story
110
118
  #
111
119
  # On Wednesday, 07 Jun 2017 at 2:37 PM, Rob Owens created the following Widget information:
112
120
  # • email: Tim@example.com
113
- # • name: Tim's Widget
121
+ # • name: Tim's Widget
114
122
  # • manufacturer: WidgetsAreUs[411]
115
123
  # •: 1234
116
- #
124
+ #
117
125
  # On Thursday, 23 Oct 2017 at 7:55 AM PDT, Rob Owens updated Manufacturer[411]:
118
126
  # • name: WidgetsRUs
119
- #
127
+ #
120
128
  # On Friday, 24 Oct 2017 at 10:10 AM PDT, Rob Owens created the following Attachment[212] information:
121
129
  # • name: Electromagnet
122
130
  # • widget: Tim's Widget[1234]
123
131
  # •: 212
124
- #
132
+ #
133
+ ```
134
+
135
+ `PaperTrailScrapbook` also implements a `version_filter` hook to provide a flexible way to filter which versions appear in a object's history. For example, if we only wanted our `Widget` class to include history for its manufacturer after the widget was created, we might implement `Widget#version_filter` like this:
136
+
137
+ ```ruby
138
+ class Widget < ApplicationRecord
139
+ has_paper_trail
140
+
141
+ def trailed_related_content
142
+ attachments | [manufacturer]
143
+ end
144
+
145
+ def version_filter(version)
146
+ case version.item_type
147
+ when 'Manufacturer'
148
+ if version.created_at < created_at
149
+ return nil
150
+ end
151
+ end
152
+ version
153
+ end
154
+
155
+ ...
156
+ ```
157
+
158
+ Then, the above history would be:
159
+
160
+ ```ruby
161
+ widget = Widget.find 42
162
+
163
+ text = PaperTrailScrapbook::LifeHistory.new(widget).story
164
+
165
+ # On Wednesday, 07 Jun 2017 at 2:37 PM, Rob Owens created the following Widget information:
166
+ # • email: Tim@example.com
167
+ # • name: Tim's Widget
168
+ # • manufacturer: WidgetsAreUs[411]
169
+ # •: 1234
170
+ #
171
+ # On Thursday, 23 Oct 2017 at 7:55 AM PDT, Rob Owens updated Manufacturer[411]:
172
+ # • name: WidgetsRUs
173
+ #
174
+ # On Friday, 24 Oct 2017 at 10:10 AM PDT, Rob Owens created the following Attachment[212] information:
175
+ # • name: Electromagnet
176
+ # • widget: Tim's Widget[1234]
177
+ # •: 212
178
+ #
125
179
  ```
126
180
 
127
181
  ### User Journal
@@ -191,7 +245,7 @@ text = PaperTrailScrapbook::UserJournal.new(who, start: 1.month.ago, end: Time.n
191
245
 
192
246
  ## Problems
193
247
 
194
- Please use GitHub's [issue tracker](http://github.com/tjchambers/paper_trail_scrapbook/issues).
248
+ Please use GitHub's [issue tracker](http://github.com/hintmedia/paper_trail_scrapbook/issues).
195
249
 
196
250
 
197
251
  ## Contributors
@@ -207,7 +261,7 @@ possible.
207
261
 
208
262
  ## Intellectual Property
209
263
 
210
- Copyright (c) 2017 Tim Chambers (tim@possibilogy.com).
264
+ Copyright (c) 2017 Hint Media, Inc.
211
265
  Released under the MIT licence.
212
266
 
213
267
 
@@ -3,11 +3,16 @@
3
3
  module PaperTrailScrapbook
4
4
  # Class Changes provides detailed attribute by attribute analysis
5
5
  #
6
- # @author Timothy Chambers <tim@possibilogy.com>
6
+ # @author Timothy Chambers <tim@hint.io>
7
7
  #
8
8
  class Changes
9
9
  include Concord.new(:version)
10
10
  include Adamantium::Flat
11
+ include PaperTrailScrapbook::VersionHelpers
12
+
13
+ POLYMORPH_BT_INDICATOR = '*'
14
+
15
+ delegate :object_changes, to: :version
11
16
 
12
17
  def initialize(*)
13
18
  super
@@ -23,10 +28,11 @@ module PaperTrailScrapbook
23
28
  # @return [String] Summary analysis of changes
24
29
  #
25
30
  def change_log
26
- text = changes
27
- .map { |k, v| digest(k, v) }
28
- .compact
29
- .join("\n")
31
+ text =
32
+ changes
33
+ .map { |k, v| digest(k, v) }
34
+ .compact
35
+ .join("\n")
30
36
 
31
37
  text = text.gsub(' id:', ':') if PaperTrailScrapbook.config.drop_id_suffix
32
38
  text
@@ -34,9 +40,13 @@ module PaperTrailScrapbook
34
40
 
35
41
  private
36
42
 
43
+ def polymorphic?(x)
44
+ x.to_s.start_with?(POLYMORPH_BT_INDICATOR)
45
+ end
46
+
37
47
  def digest(key, values)
38
48
  old, new = values
39
- return if old.nil? && (new.nil? || new.eql?('')) || (old == new)
49
+ return if old.nil? && (new.nil? || new.eql?('')) || (old == new && !creating?)
40
50
 
41
51
  "#{BULLET} #{key.tr('_', ' ')}: #{detailed_analysis(key, new, old)}"
42
52
  end
@@ -63,17 +73,40 @@ module PaperTrailScrapbook
63
73
  return '*empty*' unless value
64
74
 
65
75
  begin
66
- build_associations[key].find(value).to_s.to_s + "[#{value}]"
76
+ assoc_target(key).find(value).to_s.to_s + "[#{value}]"
67
77
  rescue StandardError
68
78
  "*not found*[#{value}]"
69
79
  end
70
80
  end
71
81
 
82
+ def assoc_target(key)
83
+ x = build_associations[key]
84
+ return x unless polymorphic?(x)
85
+ ref = x[1..-1] + '_type'
86
+
87
+ # try object changes to see if the belongs_to class is specified
88
+ latest_class = changes[ref]&.last
89
+
90
+ if latest_class.nil? && create?
91
+ # try the db default class
92
+ # for creates where the object changes do not specify this it
93
+ # is most likely because the default == type selected so
94
+ # the default was not changed and therefore is not in
95
+ # object changes
96
+ orig_instance = Object.const_get(version.item_type.classify).new
97
+ latest_class = orig_instance[ref.to_sym]
98
+ end
99
+
100
+ Object.const_get(latest_class.classify)
101
+ end
102
+
72
103
  def assoc_klass(name, options = {})
73
104
  direct_class = options[:class_name]
74
- return direct_class if direct_class && !direct_class.is_a?(String)
105
+ poly = options[:polymorphic]
106
+
107
+ return direct_class if !poly && direct_class && !direct_class.is_a?(String)
75
108
 
76
- Object.const_get((direct_class || name.to_s).classify)
109
+ poly ? POLYMORPH_BT_INDICATOR + name.to_s : Object.const_get((direct_class || name.to_s).classify)
77
110
  rescue StandardError
78
111
  Object.const_set(name.to_s.classify, Class.new)
79
112
  end
@@ -86,16 +119,12 @@ module PaperTrailScrapbook
86
119
  @build_associations ||=
87
120
  Hash[
88
121
  klass
89
- .reflect_on_all_associations
90
- .select { |a| a.macro.equal?(:belongs_to) }
91
- .map { |x| [x.foreign_key.to_s, assoc_klass(x.name, x.options)] }
122
+ .reflect_on_all_associations
123
+ .select { |a| a.macro.equal?(:belongs_to) }
124
+ .map { |x| [x.foreign_key.to_s, assoc_klass(x.name, x.options)] }
92
125
  ]
93
126
  end
94
127
 
95
- def object_changes
96
- version.object_changes
97
- end
98
-
99
128
  def changes
100
129
  @changes ||= if object_changes
101
130
  YAML
@@ -5,7 +5,7 @@ require_relative 'version_helpers'
5
5
  module PaperTrailScrapbook
6
6
  # Class Chapter provides single version history analysis
7
7
  #
8
- # @author Timothy Chambers <tim@possibilogy.com>
8
+ # @author Timothy Chambers <tim@hint.io>
9
9
  #
10
10
  class Chapter
11
11
  include Concord.new(:version)
@@ -22,7 +22,8 @@ module PaperTrailScrapbook
22
22
  :drop_id_suffix,
23
23
  :unknown_whodunnit,
24
24
  :invalid_whodunnit,
25
- :filter_non_changes
25
+ :filter_non_changes,
26
+ :recent_first
26
27
 
27
28
  def initialize
28
29
  @whodunnit_class = nil
@@ -33,6 +34,7 @@ module PaperTrailScrapbook
33
34
  @invalid_whodunnit = proc { |w| "*missing (#{w})*" }
34
35
  @drop_id_suffix = true
35
36
  @filter_non_changes = true
37
+ @recent_first = false
36
38
  end
37
39
  end
38
40
  end
@@ -5,7 +5,7 @@ require_relative 'version_helpers'
5
5
  module PaperTrailScrapbook
6
6
  # Class JournalEntry provides single version history analysis
7
7
  #
8
- # @author Jason Dinsmore <jason@dinjas.com>
8
+ # @author Jason Dinsmore <jason@hint.io>
9
9
  #
10
10
  class JournalEntry
11
11
  include Concord.new(:version)
@@ -3,19 +3,12 @@
3
3
  module PaperTrailScrapbook
4
4
  # Class LifeHistory provides Full multi version history
5
5
  #
6
- # @author Timothy Chambers <tim@possibilogy.com>
6
+ # @author Timothy Chambers <tim@hint.io>
7
7
  #
8
8
  class LifeHistory
9
9
  def initialize(object)
10
10
  @object = object
11
- @versions = object.versions
12
- if object.respond_to?(:trailed_related_content)
13
- object.trailed_related_content.compact.each do |trc|
14
- @versions |= trc.versions
15
- end
16
- end
17
-
18
- @versions = @versions.sort_by(&:created_at)
11
+ @versions = Versions.new(object).versions
19
12
  end
20
13
 
21
14
  # Retries textual historical analysis of versions
@@ -23,13 +16,17 @@ module PaperTrailScrapbook
23
16
  # @return [String] analyzed versions
24
17
  #
25
18
  def story
26
- versions.map do |v|
19
+ x = versions.map do |v|
27
20
  if primary?(v)
28
21
  Chapter
29
22
  else
30
23
  SecondaryChapter
31
24
  end.new(v).story
32
- end.compact.join("\n\n")
25
+ end.compact
26
+
27
+ x.reverse! if PaperTrailScrapbook.config.recent_first
28
+
29
+ x.join("\n\n")
33
30
  end
34
31
 
35
32
  private
@@ -4,7 +4,7 @@ module PaperTrailScrapbook
4
4
  # Class UserJournal provides history for a user, optionally scoped by
5
5
  # object class and/or date range
6
6
  #
7
- # @author Jason Dinsmore <jason@dinjas.com>
7
+ # @author Jason Dinsmore <jason@hint.io>
8
8
  #
9
9
  class UserJournal
10
10
  include Adamantium::Flat
@@ -26,7 +26,11 @@ module PaperTrailScrapbook
26
26
  def story
27
27
  s = versions.map do |v|
28
28
  JournalEntry.new(v).story
29
- end.compact.join("\n\n")
29
+ end.compact
30
+
31
+ s.reverse! if PaperTrailScrapbook.config.recent_first
32
+
33
+ s.join("\n\n")
30
34
 
31
35
  "#{preface}#{s.presence || 'No history'}"
32
36
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PaperTrailScrapbook
4
4
  # Current version
5
- VERSION = '0.1.13'
5
+ VERSION = '0.1.19'
6
6
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaperTrailScrapbook
4
+ class Versions
5
+ include Concord.new(:object)
6
+
7
+ def versions
8
+ filtered(object.versions | related_content).sort_by(&:created_at)
9
+ end
10
+
11
+ def related_content
12
+ unless object.respond_to?(:trailed_related_content)
13
+ return []
14
+ end
15
+
16
+ object.trailed_related_content.compact.flat_map(&:versions)
17
+ end
18
+
19
+ def filtered(object_versions)
20
+ unless object.respond_to?(:version_filter)
21
+ return object_versions
22
+ end
23
+
24
+ object_versions.select { |v| object.version_filter(v) }
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -9,9 +9,9 @@ Gem::Specification.new do |gem|
9
9
  gem.summary = 'Paper Trail Scrapbook'
10
10
  gem.description = "Human Readable Change Log for Paper Trail'd data"
11
11
  gem.authors = ['Timothy Chambers']
12
- gem.email = 'tim@possibilogy.com'
12
+ gem.email = 'tim@hint.io'
13
13
  gem.files = `git ls-files`.split("\n")
14
- gem.homepage = 'https://github.com/tjchambers/paper_trail_scrapbook'
14
+ gem.homepage = 'https://github.com/hintmedia/paper_trail_scrapbook'
15
15
  gem.license = 'MIT'
16
16
 
17
17
  gem.required_rubygems_version = '>= 1.3.6'
@@ -21,21 +21,22 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency 'activerecord'
22
22
  gem.add_dependency 'adamantium'
23
23
  gem.add_dependency 'concord'
24
- gem.add_dependency 'paper_trail', ['>= 5.2', '<= 9.2.0']
24
+ gem.add_dependency 'paper_trail', ['>= 5.2', '<= 10.2.1']
25
25
 
26
26
  gem.add_development_dependency 'ffaker', '~> 2.5'
27
- gem.add_development_dependency 'rake', '~> 10.4.2'
27
+ gem.add_development_dependency 'rake', '~> 13.0.1'
28
28
 
29
29
  # Why `railties`? Possibly used by `spec/dummy_app` boot up?
30
- gem.add_development_dependency 'railties', '= 5.2.2.1'
30
+ gem.add_development_dependency 'railties', '= 5.2.3'
31
31
 
32
32
  gem.add_development_dependency 'codeclimate-test-reporter', '~> 1.0.7'
33
33
  gem.add_development_dependency 'database_cleaner', '~> 1.2'
34
- gem.add_development_dependency 'loofah', '~> 2.2.3'
34
+ gem.add_development_dependency 'loofah', '~> 2.3.1'
35
35
  gem.add_development_dependency 'mutant'
36
36
  gem.add_development_dependency 'mutant-rspec'
37
37
  gem.add_development_dependency 'pg', '= 0.18.4'
38
38
  gem.add_development_dependency 'rspec-rails'
39
+ gem.add_development_dependency 'rspec-jumpstart'
39
40
  gem.add_development_dependency 'rspec_junit_formatter'
40
41
  gem.add_development_dependency 'rubocop'
41
42
  gem.add_development_dependency 'rubocop-rspec'
@@ -5,7 +5,7 @@ require 'securerandom'
5
5
  class CustomPrimaryKeyRecord < ActiveRecord::Base
6
6
  self.primary_key = :uuid
7
7
 
8
- has_paper_trail class_name: 'CustomPrimaryKeyRecordVersion'
8
+ has_paper_trail versions: { class_name: 'CustomPrimaryKeyRecordVersion' }
9
9
 
10
10
  # This default_scope is to test the case of the Version#item association
11
11
  # not returning the item due to unmatched default_scope on the model.
@@ -2,7 +2,7 @@
2
2
 
3
3
  class Document < ActiveRecord::Base
4
4
  has_paper_trail(
5
- versions: :paper_trail_versions,
5
+ versions: {name: :paper_trail_versions},
6
6
  on: %i[create update]
7
7
  )
8
8
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kitchen
4
4
  class Banana < ActiveRecord::Base
5
- has_paper_trail class_name: 'Kitchen::BananaVersion'
5
+ has_paper_trail versions: { class_name: 'Kitchen::BananaVersion' }
6
6
  end
7
7
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Post < ActiveRecord::Base
4
- has_paper_trail class_name: 'PostVersion'
4
+ has_paper_trail versions: { class_name: 'PostVersion' }
5
5
  end
@@ -1,3 +1 @@
1
1
  # frozen_string_literal: true
2
-
3
- PaperTrail.config.track_associations = false
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/paper_trail_scrapbook/journal_entry'
5
+
6
+ RSpec.describe PaperTrailScrapbook::JournalEntry do
7
+ let(:person) { Person.create!(name: 'The Tim Man') }
8
+ let(:book) { Book.create!(title: 'How the Grinch stole Xmas') }
9
+ let(:version) do
10
+ OpenStruct.new(event: 'create',
11
+ item_type: 'Book',
12
+ item_id: book.id,
13
+ created_at: whenn,
14
+ version_author: person.id)
15
+ end
16
+ let(:subject) { described_class.new(version) }
17
+ let(:whenn) { Time.parse('2019-12-16 12:01:29 -0800') }
18
+
19
+ describe '#story' do
20
+ it 'story' do
21
+ result = subject.story
22
+
23
+ expect(result).to eql('On Monday, 16 Dec 2019 at 12:01 PM, '\
24
+ "created Book[#{book.id}]:\n")
25
+ end
26
+ end
27
+
28
+ end
@@ -61,7 +61,7 @@ module PaperTrailScrapbook
61
61
  .to match(/How the Grinch stole Xmas\[\d+\] was \*removed\*/)
62
62
  end
63
63
 
64
- context 'it handles missing whodunnit record' do
64
+ context 'when it handles missing whodunnit record' do
65
65
  it 'provides a whole story with missing whodunnit record' do
66
66
  target
67
67
  pid = person.id
@@ -88,7 +88,7 @@ module PaperTrailScrapbook
88
88
  end
89
89
  end
90
90
 
91
- context 'no papertrail' do
91
+ context 'without papertrail' do
92
92
  let(:target) { Elephant.create! }
93
93
 
94
94
  it 'has none' do
@@ -97,6 +97,15 @@ module PaperTrailScrapbook
97
97
  end
98
98
  end
99
99
 
100
+ context 'with polymorphic data' do
101
+ let(:target) { Whatchamajigger.create!(owner: author) }
102
+
103
+ it 'locates the proper model' do
104
+ expect(subject).to match(/Dr. Seuss\[/)
105
+ expect(subject).to match(/owner type: Person/)
106
+ end
107
+ end
108
+
100
109
  context 'with related data' do
101
110
  before do
102
111
  author
@@ -120,6 +129,42 @@ module PaperTrailScrapbook
120
129
  expect(subject).to match(/author: Dr\. Seuss\[\d+\]/)
121
130
  end
122
131
  end
132
+
133
+ context 'recent first' do
134
+ before do
135
+ author
136
+ book
137
+ target
138
+
139
+ config = PaperTrailScrapbook.config
140
+ config.recent_first = true
141
+ config.time_format = '%A, %d %b %Y at %l:%M:%S.%9N %p'
142
+
143
+ def target.trailed_related_content
144
+ [book, author]
145
+ end
146
+ end
147
+
148
+ after do
149
+ config = PaperTrailScrapbook.config
150
+ config.recent_first = false
151
+ config.time_format = '%A, %d %b %Y at %l:%M %p'
152
+ end
153
+
154
+ it 'includes related content history' do
155
+ expect(subject).to match(/created the following Person\[\d+\] info/)
156
+ expect(subject).to match(/name: Dr\. Seuss/)
157
+
158
+ expect(subject).to match(/created the following Book\[\d+\] info/)
159
+ expect(subject).to match(/title: How the Grinch stole Xmas/)
160
+
161
+ expect(subject.squish).to match(/created the following Book.*created the following Person/)
162
+
163
+ expect(subject).to match(/created the following Authorship info/)
164
+ expect(subject).to match(/book: How the Grinch stole Xmas\[\d+\]/)
165
+ expect(subject).to match(/author: Dr\. Seuss\[\d+\]/)
166
+ end
167
+ end
123
168
  end
124
169
  end
125
170
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'paper_trail_scrapbook/versions'
5
+
6
+ module PaperTrailScrapbook
7
+ ::RSpec.describe Versions do
8
+ before do
9
+ PaperTrailScrapbook.config.whodunnit_class = Person
10
+ PaperTrail.request.whodunnit = person.id
11
+ end
12
+
13
+ let(:book) do
14
+ Book.new(title: 'How the Grinch stole Xmas').tap(&:save!)
15
+ end
16
+ let(:person) { Person.create(name: 'The Tim Man') }
17
+ let!(:authorship) do
18
+ Authorship.new(book: book, author: person).tap(&:save!)
19
+ end
20
+
21
+ let(:object) { described_class.new(book) }
22
+
23
+ describe '#versions' do
24
+ it 'versions' do
25
+ book.update!(title: 'New Title')
26
+
27
+ result = object.versions
28
+
29
+ expect(result).to eql(book.versions.to_a)
30
+ expect(result.size).to equal(2)
31
+ end
32
+ end
33
+
34
+ describe '#related_content' do
35
+ it 'related_content returns nothing if no related content' do
36
+ result = object.related_content
37
+
38
+ expect(result).to eql([])
39
+ end
40
+
41
+ it 'returns related content' do
42
+ allow(book).to receive(:respond_to?)
43
+ .with(:trailed_related_content).and_return(true)
44
+ allow(book).to receive(:respond_to?)
45
+ .with(:trailed_related_content, true).and_return(true)
46
+ allow(book).to receive(:trailed_related_content) do
47
+ book.authorships
48
+ end
49
+
50
+ result = object.related_content
51
+
52
+ expect(result).to eql(authorship.versions.to_a)
53
+ end
54
+ end
55
+
56
+ describe '#filtered' do
57
+ it 'returns versions if no filter' do
58
+ result = object.filtered(book.versions.to_a)
59
+
60
+ expect(result).to eql(book.versions.to_a)
61
+ end
62
+
63
+ it 'returns filtered versions if filter' do
64
+ allow(book).to receive(:respond_to?)
65
+ .with(:version_filter, true).and_return(true)
66
+ allow(book).to receive(:respond_to?)
67
+ .with(:version_filter).and_return(true)
68
+ allow(book).to receive(:version_filter) do |_version|
69
+ nil
70
+ end
71
+
72
+ result = object.filtered(book.versions.to_a)
73
+
74
+ expect(result).to eql([])
75
+ end
76
+
77
+ it 'returns filtered versions if filter' do
78
+ book.update!(title: 'New Title')
79
+
80
+ allow(book).to receive(:respond_to?).with(:version_filter, true).and_return(true)
81
+ allow(book).to receive(:respond_to?).with(:version_filter).and_return(true)
82
+ allow(book).to receive(:version_filter) do |version|
83
+ if version.event.eql?('update')
84
+ version
85
+ end
86
+ end
87
+
88
+ result = object.filtered(book.versions)
89
+
90
+ expect(result).to eql([book.versions.last])
91
+ expect(result.size).not_to eql(book.versions.size)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -2,5 +2,13 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- module PaperTrailScrapbook
5
+ RSpec.describe PaperTrailScrapbook do
6
+ describe '.config' do
7
+ it 'sets the @config ivar' do
8
+ described_class.config
9
+
10
+ expect(described_class.instance_variable_get(:@config))
11
+ .to equal(PaperTrailScrapbook::Config.instance)
12
+ end
13
+ end
6
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paper_trail_scrapbook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timothy Chambers
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-28 00:00:00.000000000 Z
11
+ date: 2020-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -61,7 +61,7 @@ dependencies:
61
61
  version: '5.2'
62
62
  - - "<="
63
63
  - !ruby/object:Gem::Version
64
- version: 9.2.0
64
+ version: 10.2.1
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
@@ -71,7 +71,7 @@ dependencies:
71
71
  version: '5.2'
72
72
  - - "<="
73
73
  - !ruby/object:Gem::Version
74
- version: 9.2.0
74
+ version: 10.2.1
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: ffaker
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -92,28 +92,28 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 10.4.2
95
+ version: 13.0.1
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: 10.4.2
102
+ version: 13.0.1
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: railties
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: 5.2.2.1
109
+ version: 5.2.3
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - '='
115
115
  - !ruby/object:Gem::Version
116
- version: 5.2.2.1
116
+ version: 5.2.3
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: codeclimate-test-reporter
119
119
  requirement: !ruby/object:Gem::Requirement
@@ -148,14 +148,14 @@ dependencies:
148
148
  requirements:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: 2.2.3
151
+ version: 2.3.1
152
152
  type: :development
153
153
  prerelease: false
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: 2.2.3
158
+ version: 2.3.1
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: mutant
161
161
  requirement: !ruby/object:Gem::Requirement
@@ -212,6 +212,20 @@ dependencies:
212
212
  - - ">="
213
213
  - !ruby/object:Gem::Version
214
214
  version: '0'
215
+ - !ruby/object:Gem::Dependency
216
+ name: rspec-jumpstart
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ type: :development
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
215
229
  - !ruby/object:Gem::Dependency
216
230
  name: rspec_junit_formatter
217
231
  requirement: !ruby/object:Gem::Requirement
@@ -297,7 +311,7 @@ dependencies:
297
311
  - !ruby/object:Gem::Version
298
312
  version: 2.0.6
299
313
  description: Human Readable Change Log for Paper Trail'd data
300
- email: tim@possibilogy.com
314
+ email: tim@hint.io
301
315
  executables: []
302
316
  extensions: []
303
317
  extra_rdoc_files: []
@@ -326,6 +340,7 @@ files:
326
340
  - lib/paper_trail_scrapbook/user_journal.rb
327
341
  - lib/paper_trail_scrapbook/version.rb
328
342
  - lib/paper_trail_scrapbook/version_helpers.rb
343
+ - lib/paper_trail_scrapbook/versions.rb
329
344
  - log/mutant/pts.log
330
345
  - paper_trail_scrapbook.gemspec
331
346
  - pkg/paper_trail_scrapbook-0.0.2.gem
@@ -405,18 +420,20 @@ files:
405
420
  - spec/paper_trail_scrapbook/changes_spec.rb
406
421
  - spec/paper_trail_scrapbook/chapter_spec.rb
407
422
  - spec/paper_trail_scrapbook/config_spec.rb
423
+ - spec/paper_trail_scrapbook/journal_entry_spec.rb
408
424
  - spec/paper_trail_scrapbook/life_history_spec.rb
409
425
  - spec/paper_trail_scrapbook/secondary_chapter_spec.rb
410
426
  - spec/paper_trail_scrapbook/user_journal_spec.rb
411
427
  - spec/paper_trail_scrapbook/version_helpers_spec.rb
412
428
  - spec/paper_trail_scrapbook/version_spec.rb
429
+ - spec/paper_trail_scrapbook/versions_spec.rb
413
430
  - spec/paper_trail_scrapbook_spec.rb
414
431
  - spec/spec_helper.rb
415
- homepage: https://github.com/tjchambers/paper_trail_scrapbook
432
+ homepage: https://github.com/hintmedia/paper_trail_scrapbook
416
433
  licenses:
417
434
  - MIT
418
435
  metadata: {}
419
- post_install_message:
436
+ post_install_message:
420
437
  rdoc_options: []
421
438
  require_paths:
422
439
  - lib
@@ -431,9 +448,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
431
448
  - !ruby/object:Gem::Version
432
449
  version: 1.3.6
433
450
  requirements: []
434
- rubyforge_project:
451
+ rubyforge_project:
435
452
  rubygems_version: 2.5.2.3
436
- signing_key:
453
+ signing_key:
437
454
  specification_version: 4
438
455
  summary: Paper Trail Scrapbook
439
456
  test_files: []