paper_trail_scrapbook 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +2 -3
- data/.rubocop.yml +12 -0
- data/Changelog.md +33 -0
- data/Gemfile.lock +12 -3
- data/README.md +3 -1
- data/Rakefile +1 -1
- data/circle.yml +11 -0
- data/lib/paper_trail_scrapbook/changes.rb +33 -13
- data/lib/paper_trail_scrapbook/chapter.rb +29 -16
- data/lib/paper_trail_scrapbook/config.rb +21 -2
- data/lib/paper_trail_scrapbook/life_history.rb +8 -0
- data/lib/paper_trail_scrapbook/version.rb +1 -1
- data/lib/paper_trail_scrapbook.rb +0 -21
- data/paper_trail_scrapbook.gemspec +8 -8
- data/pkg/paper_trail_scrapbook-0.0.2.gem +0 -0
- data/spec/dummy_app/app/models/book.rb +4 -0
- data/spec/dummy_app/app/models/person.rb +2 -31
- data/spec/dummy_app/config/application.rb +1 -1
- data/spec/dummy_app/config/initializers/secret_token.rb +1 -3
- data/spec/paper_trail_scrapbook/changes_spec.rb +102 -0
- data/spec/paper_trail_scrapbook/chapter_spec.rb +51 -0
- data/spec/paper_trail_scrapbook/life_history_spec.rb +58 -0
- data/spec/spec_helper.rb +6 -0
- metadata +41 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ac66380142b8a42d963d1b055d86af95dea2b43
|
4
|
+
data.tar.gz: 025ff0a7bbda3e96016f9c45258aff25c0303d62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c3a37a779364362adca498d79a92df27faf9201d177e99dc7705761c2ddb301c081c6fcd17e2448f9abab21154e334e7d9bc29e4f0afeb651cad77719d5611a
|
7
|
+
data.tar.gz: 9c95389f5e9b8c95281ceb7f7e7902d4f99e7a84f4c9913fa13a6faeb00a5516f4ffae33230dbf170a67ffdd05d9b74ce9537dd20067ebf2f46441e620236bdf
|
data/.codeclimate.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -3,6 +3,18 @@ AllCops:
|
|
3
3
|
TargetRubyVersion: 2.2
|
4
4
|
TargetRailsVersion: 4.0
|
5
5
|
DisplayCopNames: true
|
6
|
+
Exclude:
|
7
|
+
- 'db/**/*'
|
8
|
+
- 'config/**/*'
|
9
|
+
- 'script/**/*'
|
10
|
+
- 'vendor/**/*'
|
11
|
+
- 'test/**/*'
|
12
|
+
- 'bin/**/*'
|
13
|
+
- 'spec/dummy_app/db/**/*'
|
6
14
|
|
7
15
|
Security/YAMLLoad:
|
8
16
|
Enabled: false
|
17
|
+
|
18
|
+
# Limit line length
|
19
|
+
Metrics/LineLength:
|
20
|
+
Max: 150
|
data/Changelog.md
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
|
4
|
+
recommendations of [keepachangelog.com](http://keepachangelog.com/).
|
5
|
+
|
6
|
+
## Unreleased
|
7
|
+
|
8
|
+
### Breaking Changes
|
9
|
+
|
10
|
+
- None
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- None
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
- None
|
19
|
+
|
20
|
+
## 0.1.0 (2017-06-30) Initial Release
|
21
|
+
|
22
|
+
### Breaking Changes
|
23
|
+
|
24
|
+
- None
|
25
|
+
|
26
|
+
### Added
|
27
|
+
|
28
|
+
- Initial Public Release
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
|
32
|
+
- None
|
33
|
+
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
paper_trail_scrapbook (0.0.
|
4
|
+
paper_trail_scrapbook (0.0.6)
|
5
5
|
activerecord (>= 4.0, < 5.2)
|
6
6
|
adamantium
|
7
7
|
concord
|
8
8
|
paper_trail
|
9
|
-
request_store (~> 1.1)
|
10
9
|
|
11
10
|
GEM
|
12
11
|
remote: http://rubygems.org/
|
@@ -41,17 +40,21 @@ GEM
|
|
41
40
|
arel (8.0.0)
|
42
41
|
ast (2.3.0)
|
43
42
|
builder (3.2.3)
|
43
|
+
codeclimate-test-reporter (1.0.7)
|
44
|
+
simplecov
|
44
45
|
concord (0.1.5)
|
45
46
|
adamantium (~> 0.2.0)
|
46
47
|
equalizer (~> 0.0.9)
|
47
48
|
concurrent-ruby (1.0.5)
|
48
49
|
database_cleaner (1.6.1)
|
49
50
|
diff-lcs (1.3)
|
51
|
+
docile (1.1.5)
|
50
52
|
equalizer (0.0.11)
|
51
53
|
erubi (1.6.1)
|
52
54
|
ffaker (2.6.0)
|
53
55
|
i18n (0.8.4)
|
54
56
|
ice_nine (0.11.2)
|
57
|
+
json (2.1.0)
|
55
58
|
loofah (2.0.3)
|
56
59
|
nokogiri (>= 1.5.9)
|
57
60
|
memoizable (0.4.2)
|
@@ -113,6 +116,11 @@ GEM
|
|
113
116
|
rubocop-rspec (1.15.1)
|
114
117
|
rubocop (>= 0.42.0)
|
115
118
|
ruby-progressbar (1.8.1)
|
119
|
+
simplecov (0.14.1)
|
120
|
+
docile (~> 1.1.0)
|
121
|
+
json (>= 1.8, < 3)
|
122
|
+
simplecov-html (~> 0.10.0)
|
123
|
+
simplecov-html (0.10.1)
|
116
124
|
sqlite3 (1.3.13)
|
117
125
|
thor (0.19.4)
|
118
126
|
thread_safe (0.3.6)
|
@@ -125,15 +133,16 @@ PLATFORMS
|
|
125
133
|
ruby
|
126
134
|
|
127
135
|
DEPENDENCIES
|
136
|
+
codeclimate-test-reporter
|
128
137
|
database_cleaner (~> 1.2)
|
129
138
|
ffaker (~> 2.5)
|
130
139
|
paper_trail_scrapbook!
|
131
140
|
railties (>= 4.0, < 5.2)
|
132
141
|
rake (~> 12.0)
|
133
|
-
rspec-core (~> 3.6)
|
134
142
|
rspec-rails (~> 3.6)
|
135
143
|
rubocop
|
136
144
|
rubocop-rspec
|
145
|
+
simplecov
|
137
146
|
sqlite3
|
138
147
|
timecop (~> 0.8.0)
|
139
148
|
|
data/README.md
CHANGED
@@ -19,7 +19,9 @@ then you should configure this into the scrapbook so it can locate and provide a
|
|
19
19
|
|
20
20
|
Create an initializer i.e. _config/initializers/paper_trail_scrapbook.rb
|
21
21
|
```ruby
|
22
|
-
PaperTrailScrapbook.
|
22
|
+
PaperTrailScrapbook.configure do |config|
|
23
|
+
config.whodunnit_class = User
|
24
|
+
end
|
23
25
|
|
24
26
|
```
|
25
27
|
|
data/Rakefile
CHANGED
data/circle.yml
CHANGED
@@ -2,9 +2,20 @@
|
|
2
2
|
machine:
|
3
3
|
ruby:
|
4
4
|
version: '2.2.7'
|
5
|
+
environment:
|
6
|
+
CC_TEST_REPORTER_ID: e0db6fd6beb8208980b2908947735982fb5a4e8a9a3cb742dc194e00df79f388
|
7
|
+
|
5
8
|
dependencies:
|
6
9
|
pre:
|
7
10
|
- gem install bundler
|
11
|
+
|
12
|
+
database:
|
13
|
+
override:
|
14
|
+
- echo "no db"
|
8
15
|
test:
|
16
|
+
|
9
17
|
override:
|
10
18
|
- bundle exec rake spec
|
19
|
+
- CODECLIMATE_REPO_TOKEN=e0db6fd6beb8208980b2908947735982fb5a4e8a9a3cb742dc194e00df79f388 bundle exec codeclimate-test-reporter
|
20
|
+
|
21
|
+
|
@@ -1,17 +1,33 @@
|
|
1
1
|
module PaperTrailScrapbook
|
2
|
+
# Class Changes provides detailed attribute by attribute analysis
|
3
|
+
#
|
4
|
+
# @author Timothy Chambers <tim@possibilogy.com>
|
5
|
+
#
|
2
6
|
class Changes
|
3
7
|
include Concord.new(:version)
|
8
|
+
include Adamantium::Flat
|
4
9
|
|
5
10
|
def initialize(*)
|
6
11
|
super
|
7
|
-
|
8
12
|
build_associations
|
13
|
+
changes
|
9
14
|
end
|
10
15
|
|
11
16
|
BULLET = ' •'.freeze
|
12
17
|
|
18
|
+
# Attribute change analysis
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# @return [String] Summary analysis of changes
|
22
|
+
#
|
13
23
|
def change_log
|
14
|
-
|
24
|
+
text = changes
|
25
|
+
.map { |k, v| digest(k, v) }
|
26
|
+
.compact
|
27
|
+
.join("\n")
|
28
|
+
|
29
|
+
text = text.gsub('_id:', ':') if PaperTrailScrapbook.config.drop_id_suffix
|
30
|
+
text
|
15
31
|
end
|
16
32
|
|
17
33
|
private
|
@@ -20,15 +36,19 @@ module PaperTrailScrapbook
|
|
20
36
|
old, new = v
|
21
37
|
return if old.nil? && (new.nil? || new.eql?(''))
|
22
38
|
|
23
|
-
"#{BULLET} #{k}:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
39
|
+
"#{BULLET} #{k}: #{detailed_analysis(k, new, old)}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def detailed_analysis(k, new, old)
|
43
|
+
if creating?
|
44
|
+
find_value(k, new).to_s
|
45
|
+
elsif old.nil?
|
46
|
+
"#{find_value(k, new)} added"
|
47
|
+
elsif new.nil?
|
48
|
+
"#{find_value(k, old)} was *removed*"
|
49
|
+
else
|
50
|
+
"#{find_value(k, old)} -> #{find_value(k, new)}"
|
51
|
+
end
|
32
52
|
end
|
33
53
|
|
34
54
|
def creating?
|
@@ -41,7 +61,7 @@ module PaperTrailScrapbook
|
|
41
61
|
return '*empty*' unless value
|
42
62
|
|
43
63
|
begin
|
44
|
-
assoc[key].find(value).to_s + "[#{value}]"
|
64
|
+
assoc[key].find(value).to_s.to_s + "[#{value}]"
|
45
65
|
rescue
|
46
66
|
"*not found*[#{value}]"
|
47
67
|
end
|
@@ -78,7 +98,7 @@ module PaperTrailScrapbook
|
|
78
98
|
@chs ||= if object_changes
|
79
99
|
YAML
|
80
100
|
.load(object_changes)
|
81
|
-
.except(
|
101
|
+
.except(*PaperTrailScrapbook.config.scrub_columns)
|
82
102
|
else
|
83
103
|
{}
|
84
104
|
end
|
@@ -1,49 +1,62 @@
|
|
1
1
|
module PaperTrailScrapbook
|
2
|
+
# Class Chapter provides single version history analysis
|
3
|
+
#
|
4
|
+
# @author Timothy Chambers <tim@possibilogy.com>
|
5
|
+
#
|
2
6
|
class Chapter
|
3
7
|
include Concord.new(:version)
|
8
|
+
include Adamantium::Flat
|
4
9
|
|
5
|
-
|
6
|
-
|
10
|
+
# Single version historical analysis
|
11
|
+
#
|
12
|
+
# @return [String] Human readable description of changes
|
13
|
+
#
|
7
14
|
def story
|
8
|
-
"
|
15
|
+
"#{preface}\\n#{changes}"
|
9
16
|
end
|
10
17
|
|
11
18
|
private
|
12
19
|
|
20
|
+
def preface
|
21
|
+
"On #{whenn}, #{who} #{kind} the following #{model} info:".squeeze(' ')
|
22
|
+
end
|
23
|
+
|
13
24
|
def model
|
14
25
|
version.item_type
|
15
26
|
end
|
16
27
|
|
17
28
|
def changes
|
18
|
-
|
29
|
+
Changes.new(version).change_log
|
19
30
|
end
|
20
31
|
|
21
32
|
def who
|
22
33
|
author = version.version_author
|
23
34
|
if author
|
24
|
-
if
|
25
|
-
|
35
|
+
if whodunnit_class
|
36
|
+
whodunnit_class.find(author).to_s
|
26
37
|
else
|
27
38
|
author
|
28
39
|
end
|
29
40
|
else
|
30
|
-
|
41
|
+
config.unknown_whodunnit
|
31
42
|
end
|
32
43
|
end
|
33
44
|
|
45
|
+
def whodunnit_class
|
46
|
+
config.whodunnit_class
|
47
|
+
end
|
48
|
+
|
49
|
+
def config
|
50
|
+
PaperTrailScrapbook.config
|
51
|
+
end
|
52
|
+
|
34
53
|
def whenn
|
35
|
-
version.created_at.strftime(
|
54
|
+
version.created_at.strftime(config.time_format)
|
36
55
|
end
|
37
56
|
|
38
57
|
def kind
|
39
|
-
|
40
|
-
|
41
|
-
'created'
|
42
|
-
when 'update'
|
43
|
-
'updated'
|
44
|
-
when 'destroy'
|
45
|
-
'destroyed'
|
46
|
-
end
|
58
|
+
config.events[version.event] ||
|
59
|
+
raise(ArgumentError, "incorrect event:#{version.event}")
|
47
60
|
end
|
48
61
|
end
|
49
62
|
end
|
@@ -5,9 +5,28 @@ module PaperTrailScrapbook
|
|
5
5
|
class Config
|
6
6
|
include Singleton
|
7
7
|
|
8
|
+
DEFAULT_TIME_FORMAT = '%A, %d %b %Y at %l:%M %p'.freeze
|
9
|
+
DEFAULT_EVENTS = { 'create' => 'created',
|
10
|
+
'update' => 'updated',
|
11
|
+
'destroy' => 'destroyed' }.freeze
|
12
|
+
|
13
|
+
SCRUB_COLUMNS = %w(updated_at created_at id).freeze
|
14
|
+
UNKNOWN_WHODUNNIT = '*the app*'.freeze
|
15
|
+
|
16
|
+
attr_accessor :whodunnit_class,
|
17
|
+
:time_format,
|
18
|
+
:events,
|
19
|
+
:scrub_columns,
|
20
|
+
:drop_id_suffix,
|
21
|
+
:unknown_whodunnit
|
22
|
+
|
8
23
|
def initialize
|
9
|
-
|
10
|
-
@
|
24
|
+
@whodunnit_class = nil
|
25
|
+
@time_format = DEFAULT_TIME_FORMAT
|
26
|
+
@events = DEFAULT_EVENTS
|
27
|
+
@scrub_columns = SCRUB_COLUMNS
|
28
|
+
@unknown_whodunnit = UNKNOWN_WHODUNNIT
|
29
|
+
@drop_id_suffix = true
|
11
30
|
end
|
12
31
|
end
|
13
32
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module PaperTrailScrapbook
|
2
|
+
# Class LifeHistory provides Full multi version history
|
3
|
+
#
|
4
|
+
# @author Timothy Chambers <tim@possibilogy.com>
|
5
|
+
#
|
2
6
|
class LifeHistory
|
3
7
|
def initialize(object)
|
4
8
|
@versions = object.versions
|
5
9
|
end
|
6
10
|
|
11
|
+
# Retries textual historical analysis of versions
|
12
|
+
#
|
13
|
+
# @return [String] analyzed versions
|
14
|
+
#
|
7
15
|
def story
|
8
16
|
versions.map do |v|
|
9
17
|
Chapter.new(v).story
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'adamantium'
|
2
2
|
require 'concord'
|
3
|
-
require 'digest/sha1'
|
4
3
|
require 'equalizer'
|
5
4
|
require 'ice_nine'
|
6
5
|
require 'pathname'
|
@@ -15,26 +14,6 @@ require 'paper_trail_scrapbook/version'
|
|
15
14
|
# @api private
|
16
15
|
module PaperTrailScrapbook
|
17
16
|
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
17
|
# Returns PaperTrailScrapbook's configuration object.
|
39
18
|
# @api private
|
40
19
|
def config
|
@@ -17,10 +17,9 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
# Rails does not follow semver, makes breaking changes in minor versions.
|
19
19
|
gem.add_dependency 'activerecord', ['>= 4.0', '< 5.2']
|
20
|
-
gem.add_dependency '
|
21
|
-
gem.add_dependency '
|
22
|
-
gem.add_dependency '
|
23
|
-
gem.add_dependency 'paper_trail'
|
20
|
+
gem.add_dependency 'adamantium', '~> 0'
|
21
|
+
gem.add_dependency 'concord', '~> 0'
|
22
|
+
gem.add_dependency 'paper_trail', '~> 0'
|
24
23
|
|
25
24
|
gem.add_development_dependency 'rake', '~> 12.0'
|
26
25
|
gem.add_development_dependency 'ffaker', '~> 2.5'
|
@@ -29,10 +28,11 @@ Gem::Specification.new do |gem|
|
|
29
28
|
gem.add_development_dependency 'railties', ['>= 4.0', '< 5.2']
|
30
29
|
|
31
30
|
gem.add_development_dependency 'rspec-rails', '~> 3.6'
|
32
|
-
gem.add_development_dependency 'rspec-core', '~> 3.6'
|
33
31
|
gem.add_development_dependency 'database_cleaner', '~> 1.2'
|
34
|
-
gem.add_development_dependency 'rubocop'
|
35
|
-
gem.add_development_dependency 'rubocop-rspec'
|
32
|
+
gem.add_development_dependency 'rubocop', '~> 0'
|
33
|
+
gem.add_development_dependency 'rubocop-rspec', '~> 0'
|
36
34
|
gem.add_development_dependency 'timecop', '~> 0.8.0'
|
37
|
-
gem.add_development_dependency 'sqlite3'
|
35
|
+
gem.add_development_dependency 'sqlite3', '~> 0'
|
36
|
+
gem.add_development_dependency 'simplecov', '~> 0'
|
37
|
+
gem.add_development_dependency 'codeclimate-test-reporter', '~> 0'
|
38
38
|
end
|
Binary file
|
@@ -4,36 +4,7 @@ class Person < ActiveRecord::Base
|
|
4
4
|
belongs_to :mentor, class_name: 'Person', foreign_key: :mentor_id
|
5
5
|
has_paper_trail
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
if value.is_a? ActiveSupport::TimeZone
|
10
|
-
super
|
11
|
-
else
|
12
|
-
zone = ::Time.find_zone(value) # nil if can't find time zone
|
13
|
-
super zone
|
14
|
-
end
|
7
|
+
def to_s
|
8
|
+
name
|
15
9
|
end
|
16
|
-
|
17
|
-
# Store TimeZone objects as strings when serialized to database
|
18
|
-
class TimeZoneSerializer
|
19
|
-
class << self
|
20
|
-
def dump(zone)
|
21
|
-
zone.try(:name)
|
22
|
-
end
|
23
|
-
|
24
|
-
def load(value)
|
25
|
-
::Time.find_zone(value)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def dump(zone)
|
30
|
-
self.class.dump(zone)
|
31
|
-
end
|
32
|
-
|
33
|
-
def load(value)
|
34
|
-
self.class.load(value)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
serialize :time_zone, TimeZoneSerializer.new
|
39
10
|
end
|
@@ -20,7 +20,7 @@ module Dummy
|
|
20
20
|
# we drop support for rails 4.2, we can remove this whole conditional.
|
21
21
|
config.assets.enabled = false if config.respond_to?(:assets)
|
22
22
|
|
23
|
-
config.secret_key_base = 'A
|
23
|
+
config.secret_key_base = 'A dog regularly kicked the screaming pile of biscuits.'
|
24
24
|
|
25
25
|
# `raise_in_transactional_callbacks` was added in rails 4, then deprecated
|
26
26
|
# in rails 5. Oh, how fickle are the gods.
|
@@ -4,6 +4,4 @@
|
|
4
4
|
# If you change this key, all old signed cookies will become invalid!
|
5
5
|
# Make sure the secret is at least 30 characters and all random,
|
6
6
|
# no regular words or you'll be exposed to dictionary attacks.
|
7
|
-
Dummy::Application.config.secret_token = '
|
8
|
-
'17741398ec8022a2f4fb509c57f55b72486573e9816a026f507efbcd452a9e954d45c93c' \
|
9
|
-
'95d5bacd87e664ad6805d3f'
|
7
|
+
Dummy::Application.config.secret_token = 'B264D8687B13FFFBCE757275A1314FB13B8B3BBC0B67C5ECB9B7C284A99C2747'
|
@@ -2,5 +2,107 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module PaperTrailScrapbook
|
4
4
|
::RSpec.describe Changes do
|
5
|
+
let(:version) do
|
6
|
+
OpenStruct.new(id: 2_674_798,
|
7
|
+
item_type: 'Widget',
|
8
|
+
item_id: 4804,
|
9
|
+
event: 'update',
|
10
|
+
whodunnit: '1742',
|
11
|
+
object: ['---',
|
12
|
+
'id: ',
|
13
|
+
'amount: ',
|
14
|
+
'authorization_id: ',
|
15
|
+
'paid_on: ',
|
16
|
+
'created_at: ',
|
17
|
+
'updated_at: ',
|
18
|
+
'status: active',
|
19
|
+
'name: ',
|
20
|
+
'email: ',
|
21
|
+
'x_address: ',
|
22
|
+
'notes: ',
|
23
|
+
'internal_notes: ',
|
24
|
+
'discount_percent: !ruby/object:BigDecimal 18:0.0',
|
25
|
+
'order_number: ',
|
26
|
+
'sponsor_delivery_date: ',
|
27
|
+
'other_terms: ',
|
28
|
+
'payment_terms_cd: ',
|
29
|
+
'payment_due_date: ',
|
30
|
+
'other_payment_terms: ',
|
31
|
+
'created_by: ',
|
32
|
+
'sent: false',
|
33
|
+
'token: ',
|
34
|
+
'discounted_amount: '].join("\n"),
|
35
|
+
created_at: Time.current,
|
36
|
+
object_changes: ['---',
|
37
|
+
'email:',
|
38
|
+
'- ',
|
39
|
+
'- tim@redbox.com',
|
40
|
+
'name:',
|
41
|
+
'- ',
|
42
|
+
'- Tim Chambers',
|
43
|
+
'order_number:',
|
44
|
+
'- ',
|
45
|
+
"- ''",
|
46
|
+
'notes:',
|
47
|
+
'- ',
|
48
|
+
"- ''",
|
49
|
+
'internal_notes:',
|
50
|
+
'- ',
|
51
|
+
"- ' '",
|
52
|
+
'other_terms:',
|
53
|
+
'- ',
|
54
|
+
"- ' '",
|
55
|
+
'payment_terms_cd:',
|
56
|
+
'- ',
|
57
|
+
'- 1',
|
58
|
+
'other_payment_terms:',
|
59
|
+
'- ',
|
60
|
+
"- ' '",
|
61
|
+
'sent:',
|
62
|
+
'- false',
|
63
|
+
'- true',
|
64
|
+
'created_by:',
|
65
|
+
'- ',
|
66
|
+
'- 1742',
|
67
|
+
'amount:',
|
68
|
+
'- ',
|
69
|
+
'- 29612.0',
|
70
|
+
'discounted_amount:',
|
71
|
+
'- ',
|
72
|
+
'- !ruby/object:BigDecimal 36:0.29612E5',
|
73
|
+
'created_at:',
|
74
|
+
'- ',
|
75
|
+
'- &1 2017-06-07 21:37:02.188657104 Z',
|
76
|
+
'updated_at:',
|
77
|
+
'- ',
|
78
|
+
'- *1',
|
79
|
+
'id:',
|
80
|
+
'- ',
|
81
|
+
'- 4806',
|
82
|
+
'status:',
|
83
|
+
'- active',
|
84
|
+
'- issued'].join("\n"))
|
85
|
+
end
|
86
|
+
|
87
|
+
let(:object) { described_class.new(version) }
|
88
|
+
let(:subject) { object.change_log }
|
89
|
+
|
90
|
+
describe '#change_log' do
|
91
|
+
it 'provides a set of update changes' do
|
92
|
+
expect(subject).to match(/discounted_amount: 29612.0 added/)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'filters the proper columns' do
|
96
|
+
expect(subject).not_to match(/created_at:/)
|
97
|
+
expect(subject).not_to match(/updated_at:/)
|
98
|
+
expect(subject).not_to match(/id:/)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'provides a set of create changes' do
|
102
|
+
version.event = 'create'
|
103
|
+
|
104
|
+
expect(subject).to match(/discounted_amount: 29612.0$/)
|
105
|
+
end
|
106
|
+
end
|
5
107
|
end
|
6
108
|
end
|
@@ -2,5 +2,56 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module PaperTrailScrapbook
|
4
4
|
::RSpec.describe Chapter do
|
5
|
+
let(:version) do
|
6
|
+
OpenStruct.new(id: 2_674_798,
|
7
|
+
item_type: 'Widget',
|
8
|
+
item_id: 4804,
|
9
|
+
event: 'update',
|
10
|
+
whodunnit: '1742',
|
11
|
+
object: ['---',
|
12
|
+
'id: ',
|
13
|
+
'discounted_amount: '].join("\n"),
|
14
|
+
created_at: Time.current,
|
15
|
+
object_changes: ['---',
|
16
|
+
'email:',
|
17
|
+
'- ',
|
18
|
+
'- tim@redbox.com',
|
19
|
+
'name:',
|
20
|
+
'- ',
|
21
|
+
'- Tim Chambers',
|
22
|
+
'sent:',
|
23
|
+
'- false',
|
24
|
+
'- true',
|
25
|
+
'created_by:',
|
26
|
+
'- ',
|
27
|
+
'- 1742',
|
28
|
+
'amount:',
|
29
|
+
'- ',
|
30
|
+
'- 29612.0',
|
31
|
+
'discounted_amount:',
|
32
|
+
'- ',
|
33
|
+
'- !ruby/object:BigDecimal 36:0.29612E5',
|
34
|
+
'created_at:',
|
35
|
+
'- ',
|
36
|
+
'- &1 2017-06-07 21:37:02.188657104 Z',
|
37
|
+
'updated_at:',
|
38
|
+
'- ',
|
39
|
+
'- *1',
|
40
|
+
'id:',
|
41
|
+
'- ',
|
42
|
+
'- 4806',
|
43
|
+
'status:',
|
44
|
+
'- active',
|
45
|
+
'- issued'].join("\n"))
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:object) { described_class.new(version) }
|
49
|
+
let(:subject) { object.story }
|
50
|
+
|
51
|
+
describe '#story' do
|
52
|
+
it 'provides a whole story' do
|
53
|
+
expect(subject).to match(/discounted_amount: 29612.0 added/)
|
54
|
+
end
|
55
|
+
end
|
5
56
|
end
|
6
57
|
end
|
@@ -2,5 +2,63 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module PaperTrailScrapbook
|
4
4
|
::RSpec.describe LifeHistory do
|
5
|
+
before do
|
6
|
+
PaperTrailScrapbook.config.whodunnit_class = Person
|
7
|
+
|
8
|
+
p = Person.new(name: 'The Tim Man')
|
9
|
+
p.save!
|
10
|
+
|
11
|
+
PaperTrail.whodunnit = p.id
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:book) do
|
15
|
+
b = Book.new(title: 'How the Grinch stole Xmas')
|
16
|
+
b.save!
|
17
|
+
b
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:author) do
|
21
|
+
p = Person.new(name: 'Dr. Seuss')
|
22
|
+
p.save!
|
23
|
+
p
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:target) do
|
27
|
+
a = Authorship.new(book: book, author: author)
|
28
|
+
a.save!
|
29
|
+
a
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:object) { described_class.new(target) }
|
33
|
+
let(:subject) { object.story }
|
34
|
+
|
35
|
+
describe '#story' do
|
36
|
+
it 'provides a whole story' do
|
37
|
+
expect(subject).to match(/The Tim Man/)
|
38
|
+
|
39
|
+
expect(subject).to match(/How the Grinch stole Xmas\[/)
|
40
|
+
expect(subject).to match(/Dr. Seuss\[/)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'provides a whole story missing to_s content' do
|
44
|
+
book.title = nil
|
45
|
+
book.save!
|
46
|
+
|
47
|
+
expect(subject).to match(/book: \[/)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'provides a whole story missing reference' do
|
51
|
+
book.destroy
|
52
|
+
|
53
|
+
expect(subject).to match(/book: \*not found\*\[/)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'provides a whole story missing reference' do
|
57
|
+
target.book = nil
|
58
|
+
target.save!
|
59
|
+
|
60
|
+
expect(subject).to match(/How the Grinch stole Xmas\[1\] was \*removed\*/)
|
61
|
+
end
|
62
|
+
end
|
5
63
|
end
|
6
64
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
ENV['RAILS_ENV'] ||= 'test'
|
3
3
|
ENV['DB'] ||= 'sqlite'
|
4
4
|
|
5
|
+
require 'simplecov'
|
6
|
+
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter '/spec/'
|
9
|
+
end
|
10
|
+
|
5
11
|
unless File.exist?(File.expand_path('dummy_app/config/database.yml', __dir__))
|
6
12
|
warn 'WARNING: No database.yml detected for the dummy app, please run `rake prepare` first'
|
7
13
|
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.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothy Chambers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -30,60 +30,46 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '5.2'
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: request_store
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '1.1'
|
40
|
-
type: :runtime
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - "~>"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '1.1'
|
47
33
|
- !ruby/object:Gem::Dependency
|
48
34
|
name: adamantium
|
49
35
|
requirement: !ruby/object:Gem::Requirement
|
50
36
|
requirements:
|
51
|
-
- - "
|
37
|
+
- - "~>"
|
52
38
|
- !ruby/object:Gem::Version
|
53
39
|
version: '0'
|
54
40
|
type: :runtime
|
55
41
|
prerelease: false
|
56
42
|
version_requirements: !ruby/object:Gem::Requirement
|
57
43
|
requirements:
|
58
|
-
- - "
|
44
|
+
- - "~>"
|
59
45
|
- !ruby/object:Gem::Version
|
60
46
|
version: '0'
|
61
47
|
- !ruby/object:Gem::Dependency
|
62
48
|
name: concord
|
63
49
|
requirement: !ruby/object:Gem::Requirement
|
64
50
|
requirements:
|
65
|
-
- - "
|
51
|
+
- - "~>"
|
66
52
|
- !ruby/object:Gem::Version
|
67
53
|
version: '0'
|
68
54
|
type: :runtime
|
69
55
|
prerelease: false
|
70
56
|
version_requirements: !ruby/object:Gem::Requirement
|
71
57
|
requirements:
|
72
|
-
- - "
|
58
|
+
- - "~>"
|
73
59
|
- !ruby/object:Gem::Version
|
74
60
|
version: '0'
|
75
61
|
- !ruby/object:Gem::Dependency
|
76
62
|
name: paper_trail
|
77
63
|
requirement: !ruby/object:Gem::Requirement
|
78
64
|
requirements:
|
79
|
-
- - "
|
65
|
+
- - "~>"
|
80
66
|
- !ruby/object:Gem::Version
|
81
67
|
version: '0'
|
82
68
|
type: :runtime
|
83
69
|
prerelease: false
|
84
70
|
version_requirements: !ruby/object:Gem::Requirement
|
85
71
|
requirements:
|
86
|
-
- - "
|
72
|
+
- - "~>"
|
87
73
|
- !ruby/object:Gem::Version
|
88
74
|
version: '0'
|
89
75
|
- !ruby/object:Gem::Dependency
|
@@ -149,87 +135,101 @@ dependencies:
|
|
149
135
|
- !ruby/object:Gem::Version
|
150
136
|
version: '3.6'
|
151
137
|
- !ruby/object:Gem::Dependency
|
152
|
-
name:
|
138
|
+
name: database_cleaner
|
153
139
|
requirement: !ruby/object:Gem::Requirement
|
154
140
|
requirements:
|
155
141
|
- - "~>"
|
156
142
|
- !ruby/object:Gem::Version
|
157
|
-
version: '
|
143
|
+
version: '1.2'
|
158
144
|
type: :development
|
159
145
|
prerelease: false
|
160
146
|
version_requirements: !ruby/object:Gem::Requirement
|
161
147
|
requirements:
|
162
148
|
- - "~>"
|
163
149
|
- !ruby/object:Gem::Version
|
164
|
-
version: '
|
150
|
+
version: '1.2'
|
165
151
|
- !ruby/object:Gem::Dependency
|
166
|
-
name:
|
152
|
+
name: rubocop
|
167
153
|
requirement: !ruby/object:Gem::Requirement
|
168
154
|
requirements:
|
169
155
|
- - "~>"
|
170
156
|
- !ruby/object:Gem::Version
|
171
|
-
version: '
|
157
|
+
version: '0'
|
172
158
|
type: :development
|
173
159
|
prerelease: false
|
174
160
|
version_requirements: !ruby/object:Gem::Requirement
|
175
161
|
requirements:
|
176
162
|
- - "~>"
|
177
163
|
- !ruby/object:Gem::Version
|
178
|
-
version: '
|
164
|
+
version: '0'
|
179
165
|
- !ruby/object:Gem::Dependency
|
180
|
-
name: rubocop
|
166
|
+
name: rubocop-rspec
|
181
167
|
requirement: !ruby/object:Gem::Requirement
|
182
168
|
requirements:
|
183
|
-
- - "
|
169
|
+
- - "~>"
|
184
170
|
- !ruby/object:Gem::Version
|
185
171
|
version: '0'
|
186
172
|
type: :development
|
187
173
|
prerelease: false
|
188
174
|
version_requirements: !ruby/object:Gem::Requirement
|
189
175
|
requirements:
|
190
|
-
- - "
|
176
|
+
- - "~>"
|
191
177
|
- !ruby/object:Gem::Version
|
192
178
|
version: '0'
|
193
179
|
- !ruby/object:Gem::Dependency
|
194
|
-
name:
|
180
|
+
name: timecop
|
195
181
|
requirement: !ruby/object:Gem::Requirement
|
196
182
|
requirements:
|
197
|
-
- - "
|
183
|
+
- - "~>"
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: 0.8.0
|
186
|
+
type: :development
|
187
|
+
prerelease: false
|
188
|
+
version_requirements: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - "~>"
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 0.8.0
|
193
|
+
- !ruby/object:Gem::Dependency
|
194
|
+
name: sqlite3
|
195
|
+
requirement: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - "~>"
|
198
198
|
- !ruby/object:Gem::Version
|
199
199
|
version: '0'
|
200
200
|
type: :development
|
201
201
|
prerelease: false
|
202
202
|
version_requirements: !ruby/object:Gem::Requirement
|
203
203
|
requirements:
|
204
|
-
- - "
|
204
|
+
- - "~>"
|
205
205
|
- !ruby/object:Gem::Version
|
206
206
|
version: '0'
|
207
207
|
- !ruby/object:Gem::Dependency
|
208
|
-
name:
|
208
|
+
name: simplecov
|
209
209
|
requirement: !ruby/object:Gem::Requirement
|
210
210
|
requirements:
|
211
211
|
- - "~>"
|
212
212
|
- !ruby/object:Gem::Version
|
213
|
-
version: 0
|
213
|
+
version: '0'
|
214
214
|
type: :development
|
215
215
|
prerelease: false
|
216
216
|
version_requirements: !ruby/object:Gem::Requirement
|
217
217
|
requirements:
|
218
218
|
- - "~>"
|
219
219
|
- !ruby/object:Gem::Version
|
220
|
-
version: 0
|
220
|
+
version: '0'
|
221
221
|
- !ruby/object:Gem::Dependency
|
222
|
-
name:
|
222
|
+
name: codeclimate-test-reporter
|
223
223
|
requirement: !ruby/object:Gem::Requirement
|
224
224
|
requirements:
|
225
|
-
- - "
|
225
|
+
- - "~>"
|
226
226
|
- !ruby/object:Gem::Version
|
227
227
|
version: '0'
|
228
228
|
type: :development
|
229
229
|
prerelease: false
|
230
230
|
version_requirements: !ruby/object:Gem::Requirement
|
231
231
|
requirements:
|
232
|
-
- - "
|
232
|
+
- - "~>"
|
233
233
|
- !ruby/object:Gem::Version
|
234
234
|
version: '0'
|
235
235
|
description: Human Readable Change Log for Paper Trail'd data
|
@@ -256,6 +256,7 @@ files:
|
|
256
256
|
- lib/paper_trail_scrapbook/life_history.rb
|
257
257
|
- lib/paper_trail_scrapbook/version.rb
|
258
258
|
- paper_trail_scrapbook.gemspec
|
259
|
+
- pkg/paper_trail_scrapbook-0.0.2.gem
|
259
260
|
- spec/dummy_app/Rakefile
|
260
261
|
- spec/dummy_app/app/models/animal.rb
|
261
262
|
- spec/dummy_app/app/models/article.rb
|