paper_trail 5.2.0 → 5.2.1
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 +4 -4
- data/.github/CONTRIBUTING.md +2 -0
- data/.rubocop.yml +5 -2
- data/.rubocop_todo.yml +6 -3
- data/.travis.yml +2 -1
- data/Appraisals +8 -7
- data/CHANGELOG.md +26 -1
- data/README.md +66 -31
- data/doc/bug_report_template.rb +17 -19
- data/gemfiles/ar3.gemfile +1 -0
- data/gemfiles/ar4.gemfile +1 -0
- data/gemfiles/ar5.gemfile +2 -6
- data/lib/generators/paper_trail/default_initializer.rb +0 -0
- data/lib/generators/paper_trail/install_generator.rb +9 -1
- data/lib/paper_trail/attribute_serializers/cast_attribute_serializer.rb +43 -21
- data/lib/paper_trail/model_config.rb +26 -18
- data/lib/paper_trail/version_number.rb +1 -1
- data/paper_trail.gemspec +3 -4
- data/spec/models/gadget_spec.rb +1 -1
- data/spec/models/joined_version_spec.rb +4 -4
- data/spec/models/json_version_spec.rb +2 -2
- data/spec/models/kitchen/banana_spec.rb +1 -1
- data/spec/models/post_with_status_spec.rb +26 -3
- data/spec/models/version_spec.rb +5 -16
- data/spec/models/widget_spec.rb +48 -4
- data/spec/modules/paper_trail_spec.rb +2 -2
- data/spec/modules/version_number_spec.rb +1 -1
- data/spec/paper_trail_spec.rb +11 -0
- data/spec/rails_helper.rb +0 -1
- data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +1 -0
- data/test/dummy/db/schema.rb +3 -1
- data/test/functional/modular_sinatra_test.rb +1 -8
- data/test/functional/sinatra_test.rb +1 -8
- data/test/unit/model_test.rb +3 -3
- metadata +7 -22
- data/test/paper_trail_test.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 094660b594e3a7fdd137f0b9a5e586146390223d
|
4
|
+
data.tar.gz: 9b0150f21b8ce6f20b2f9aefb558d03253e0e233
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f382487c3077476976b91107d3fa4014859d028e45c5ae6d2b7f0dd5d9003ac24d1619029992f2fa4b2ffa5683be19f0142fd1d1f027f1f97182829775e00e14
|
7
|
+
data.tar.gz: 7102dab0875334e462c7ff46b7836de36028fb4ea7e1fabcf55dfcd0ec8545c56fa941ef6833f530353bf32f6aa8d42b86ee9dc64bb731cedbb0f997431a6a43
|
data/.github/CONTRIBUTING.md
CHANGED
data/.rubocop.yml
CHANGED
@@ -6,10 +6,13 @@ inherit_from: .rubocop_todo.yml
|
|
6
6
|
# - Alphabetize cops
|
7
7
|
# - Only include permanent config; temporary goes in .rubocop_todo.yml
|
8
8
|
|
9
|
-
# We do not control `schema.rb`. Exclude it from all cops.
|
10
9
|
AllCops:
|
11
10
|
Exclude:
|
12
|
-
-
|
11
|
+
- gemfiles/vendor/bundle/**/* # This dir only shows up on travis ¯\_(ツ)_/¯
|
12
|
+
- test/dummy/db/schema.rb # Generated, out of our control
|
13
|
+
|
14
|
+
# Set to lowest supported version
|
15
|
+
TargetRubyVersion: 1.9
|
13
16
|
|
14
17
|
# Migrations often contain long up/down methods, and extracting smaller methods
|
15
18
|
# from these is of questionable value.
|
data/.rubocop_todo.yml
CHANGED
@@ -5,15 +5,18 @@ Metrics/AbcSize:
|
|
5
5
|
Max: 30 # Goal: 15
|
6
6
|
|
7
7
|
Metrics/ClassLength:
|
8
|
-
Max:
|
8
|
+
Max: 327
|
9
9
|
Exclude:
|
10
10
|
- test/**/*
|
11
11
|
|
12
12
|
Metrics/CyclomaticComplexity:
|
13
|
-
Max:
|
13
|
+
Max: 8 # Goal: 6
|
14
14
|
|
15
15
|
Metrics/ModuleLength:
|
16
16
|
Max: 317
|
17
17
|
|
18
18
|
Metrics/PerceivedComplexity:
|
19
|
-
Max:
|
19
|
+
Max: 10 # Goal: 7
|
20
|
+
|
21
|
+
Style/FrozenStringLiteralComment:
|
22
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Appraisals
CHANGED
@@ -11,6 +11,7 @@ appraise "ar3" do
|
|
11
11
|
gem "activerecord", "~> 3.2.22"
|
12
12
|
gem "i18n", "~> 0.6.11"
|
13
13
|
gem "request_store", "~> 1.1.0"
|
14
|
+
gem "sinatra", "~> 1.4.6"
|
14
15
|
|
15
16
|
group :development, :test do
|
16
17
|
gem 'railties', '~> 3.2.22'
|
@@ -23,15 +24,15 @@ end
|
|
23
24
|
|
24
25
|
appraise "ar4" do
|
25
26
|
gem "activerecord", "~> 4.2"
|
27
|
+
gem "sinatra", "~> 1.4.6"
|
26
28
|
end
|
27
29
|
|
28
30
|
appraise "ar5" do
|
29
|
-
gem "activerecord", "5.0.0
|
30
|
-
gem "
|
31
|
-
gem "actionpack", "5.0.0.beta3"
|
32
|
-
gem "railties", "5.0.0.beta3"
|
33
|
-
gem "rspec-rails", "3.5.0.beta3"
|
31
|
+
gem "activerecord", "~> 5.0.0"
|
32
|
+
gem "rspec-rails", "~> 3.5.1"
|
34
33
|
gem 'rails-controller-testing'
|
35
|
-
|
36
|
-
|
34
|
+
|
35
|
+
# The AR5 version of PaperTrail is not compatible with sinatra 2 yet.
|
36
|
+
# Contributions welcome.
|
37
|
+
# gem "sinatra", "2.0.0.beta2"
|
37
38
|
end
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
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
|
2
7
|
|
3
8
|
### Breaking Changes
|
4
9
|
|
@@ -14,8 +19,28 @@
|
|
14
19
|
|
15
20
|
### Fixed
|
16
21
|
|
22
|
+
## 5.2.1 (2016-09-02)
|
23
|
+
|
24
|
+
### Breaking Changes
|
25
|
+
|
26
|
+
- None
|
27
|
+
|
28
|
+
### Deprecated
|
29
|
+
|
30
|
+
- None
|
31
|
+
|
32
|
+
### Added
|
33
|
+
|
17
34
|
- None
|
18
35
|
|
36
|
+
### Fixed
|
37
|
+
|
38
|
+
- [#857](https://github.com/airblade/paper_trail/pull/857) -
|
39
|
+
Fix deserialization of enums written by PT 4.
|
40
|
+
- [#798](https://github.com/airblade/paper_trail/issues/798) -
|
41
|
+
Fix a rare bug with serialization of enums in rails 4.2 only when
|
42
|
+
using `touch_with_version`.
|
43
|
+
|
19
44
|
## 5.2.0 (2016-06-27)
|
20
45
|
|
21
46
|
### Breaking Changes
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ has been destroyed.
|
|
11
11
|
| Version | Documentation |
|
12
12
|
| -------------- | ------------- |
|
13
13
|
| Unreleased | https://github.com/airblade/paper_trail/blob/master/README.md |
|
14
|
-
| 5.2.
|
14
|
+
| 5.2.1 | https://github.com/airblade/paper_trail/blob/v5.2.1/README.md |
|
15
15
|
| 4.2.0 | https://github.com/airblade/paper_trail/blob/v4.2.0/README.md |
|
16
16
|
| 3.0.9 | https://github.com/airblade/paper_trail/blob/v3.0.9/README.md |
|
17
17
|
| 2.7.2 | https://github.com/airblade/paper_trail/blob/v2.7.2/README.md |
|
@@ -24,6 +24,7 @@ has been destroyed.
|
|
24
24
|
- [1.b. Installation](#1b-installation)
|
25
25
|
- [1.c. Basic Usage](#1c-basic-usage)
|
26
26
|
- [1.d. API Summary](#1d-api-summary)
|
27
|
+
- [1.e. Configuration](#1e-configuration)
|
27
28
|
- [2. Limiting What is Versioned, and When](#2-limiting-what-is-versioned-and-when)
|
28
29
|
- [2.a. Choosing Lifecycle Events To Monitor](#2a-choosing-lifecycle-events-to-monitor)
|
29
30
|
- [2.b. Choosing When To Save New Versions](#2b-choosing-when-to-save-new-versions)
|
@@ -38,6 +39,7 @@ has been destroyed.
|
|
38
39
|
- [4. Saving More Information About Versions](#4-saving-more-information-about-versions)
|
39
40
|
- [4.a. Finding Out Who Was Responsible For A Change](#4a-finding-out-who-was-responsible-for-a-change)
|
40
41
|
- [4.b. Associations](#4b-associations)
|
42
|
+
- [4.b.1. Known Issues](#4b1-known-issues)
|
41
43
|
- [4.c. Storing metadata](#4c-storing-metadata)
|
42
44
|
- [5. ActiveRecord](#5-activerecord)
|
43
45
|
- [5.a. Single Table Inheritance](#5a-single-table-inheritance-sti)
|
@@ -67,7 +69,7 @@ has been destroyed.
|
|
67
69
|
|
68
70
|
`gem 'paper_trail'`
|
69
71
|
|
70
|
-
1. Add a `versions` table to your database
|
72
|
+
1. Add a `versions` table to your database and an initializer file for configuration:
|
71
73
|
|
72
74
|
```
|
73
75
|
bundle exec rails generate paper_trail:install
|
@@ -87,7 +89,7 @@ has been destroyed.
|
|
87
89
|
```
|
88
90
|
|
89
91
|
1. If your controllers have a `current_user` method, you can easily [track who
|
90
|
-
is responsible for changes](#finding-out-who-was-responsible-for-a-change)
|
92
|
+
is responsible for changes](#4a-finding-out-who-was-responsible-for-a-change)
|
91
93
|
by adding a controller callback.
|
92
94
|
|
93
95
|
```ruby
|
@@ -252,6 +254,18 @@ user_for_paper_trail
|
|
252
254
|
info_for_paper_trail
|
253
255
|
```
|
254
256
|
|
257
|
+
### 1.e. Configuration
|
258
|
+
|
259
|
+
Many aspects of PaperTrail are configurable for individual models; typically
|
260
|
+
this is achieved by passing options to the `has_paper_trail` method within
|
261
|
+
a given model.
|
262
|
+
|
263
|
+
Some aspects of PaperTrail are configured globally for all models. These
|
264
|
+
settings are assigned directly on the `PaperTrail.config` object.
|
265
|
+
A common place to put these settings is in a Rails initializer file
|
266
|
+
such as `config/initializers/paper_trail.rb` or in an environment-specific
|
267
|
+
configuration file such as `config/environments/test.rb`.
|
268
|
+
|
255
269
|
## 2. Limiting What is Versioned, and When
|
256
270
|
|
257
271
|
### 2.a. Choosing Lifecycle Events To Monitor
|
@@ -269,7 +283,7 @@ end
|
|
269
283
|
other callbacks in your model, their order relative to those installed by
|
270
284
|
PaperTrail may matter, so be aware of any potential interactions.
|
271
285
|
|
272
|
-
You may also have the `PaperTrail::Version` model save a custom string in
|
286
|
+
You may also have the `PaperTrail::Version` model save a custom string in its
|
273
287
|
`event` field instead of the typical `create`, `update`, `destroy`. PaperTrail
|
274
288
|
supplies a custom accessor method called `paper_trail_event`, which it will
|
275
289
|
attempt to use to fill the `event` field before falling back on one of the
|
@@ -431,7 +445,7 @@ Turn PaperTrail off for all threads in a `ruby` process.
|
|
431
445
|
PaperTrail.enabled = false
|
432
446
|
```
|
433
447
|
|
434
|
-
This is commonly used to speed up tests. See [Testing](#testing) below.
|
448
|
+
This is commonly used to speed up tests. See [Testing](#7-testing) below.
|
435
449
|
|
436
450
|
There is also a rails config option that does the same thing.
|
437
451
|
|
@@ -515,11 +529,12 @@ Note `version_at` gives you the object, not a version, so you don't need to call
|
|
515
529
|
Undeleting is just as simple:
|
516
530
|
|
517
531
|
```ruby
|
518
|
-
widget = Widget.find
|
532
|
+
widget = Widget.find(42)
|
519
533
|
widget.destroy
|
520
534
|
# Time passes....
|
521
|
-
|
522
|
-
widget.
|
535
|
+
versions = widget.versions # versions ordered by versions.created_at, ascending
|
536
|
+
widget = versions.last.reify # the widget as it was before destruction
|
537
|
+
widget.save # the widget lives!
|
523
538
|
```
|
524
539
|
|
525
540
|
You could even use PaperTrail to implement an undo system, [Ryan Bates has!][3]
|
@@ -749,19 +764,30 @@ string, please try the [paper_trail-globalid][37] gem.
|
|
749
764
|
|
750
765
|
### 4.b. Associations
|
751
766
|
|
752
|
-
**Experimental feature**,
|
767
|
+
**Experimental feature**, not recommended for production. See known issues
|
768
|
+
below.
|
753
769
|
|
754
770
|
PaperTrail can restore three types of associations: Has-One, Has-Many, and
|
755
|
-
Has-Many-Through. In order to do this, you will need to
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
`
|
762
|
-
|
763
|
-
|
764
|
-
|
771
|
+
Has-Many-Through. In order to do this, you will need to do two things:
|
772
|
+
|
773
|
+
1. Create a `version_associations` table
|
774
|
+
2. Set `PaperTrail.config.track_associations = true` (e.g. in an initializer)
|
775
|
+
|
776
|
+
Both will be done for you automatically if you install PaperTrail with the
|
777
|
+
`--with_associations` option
|
778
|
+
(e.g. `rails generate paper_trail:install --with-associations`)
|
779
|
+
|
780
|
+
If you want to add this functionality after the initial installation, you will
|
781
|
+
need to create the `version_associations` table manually, and you will need to
|
782
|
+
ensure that `PaperTrail.config.track_associations = true` is set.
|
783
|
+
|
784
|
+
PaperTrail will store in the `version_associations` table additional information
|
785
|
+
to correlate versions of the association and versions of the model when the
|
786
|
+
associated record is changed. When reifying the model, PaperTrail can use this
|
787
|
+
table, together with the `transaction_id` to find the correct version of the
|
788
|
+
association and reify it. The `transaction_id` is a unique id for version records
|
789
|
+
created in the same transaction. It is used to associate the version of the model
|
790
|
+
and the version of the association that are created in the same transaction.
|
765
791
|
|
766
792
|
To restore Has-One associations as they were at the time, pass option `:has_one
|
767
793
|
=> true` to `reify`. To restore Has-Many and Has-Many-Through associations, use
|
@@ -840,11 +866,17 @@ widget_0.save!
|
|
840
866
|
widget.reload.wotsit # nil
|
841
867
|
```
|
842
868
|
|
843
|
-
|
869
|
+
#### 4.b.1. Known Issues
|
844
870
|
|
845
|
-
|
846
|
-
|
847
|
-
|
871
|
+
Associations are an **experimental feature** and have the following known
|
872
|
+
issues, in order of descending importance.
|
873
|
+
|
874
|
+
1. PaperTrail only reifies the first level of associations.
|
875
|
+
1. [#542](https://github.com/airblade/paper_trail/issues/542) -
|
876
|
+
Not compatible with [transactional tests][34], aka. transactional fixtures.
|
877
|
+
1. [#841](https://github.com/airblade/paper_trail/issues/841) -
|
878
|
+
Without a workaround, reified records cannot be persisted if their associated
|
879
|
+
records have been deleted.
|
848
880
|
1. Requires database timestamp columns with fractional second precision.
|
849
881
|
- Sqlite and postgres timestamps have fractional second precision by default.
|
850
882
|
[MySQL timestamps do not][35]. Furthermore, MySQL 5.5 and earlier do not
|
@@ -853,11 +885,9 @@ widget.reload.wotsit # nil
|
|
853
885
|
rails until ActiveRecord 4.2 (https://github.com/rails/rails/pull/14359).
|
854
886
|
1. PaperTrail can't restore an association properly if the association record
|
855
887
|
can be updated to replace its parent model (by replacing the foreign key)
|
856
|
-
1. Currently PaperTrail only supports a single `version_associations` table.
|
857
|
-
|
888
|
+
1. Currently PaperTrail only supports a single `version_associations` table.
|
889
|
+
Therefore, you can only use a single table to store the versions for
|
858
890
|
all related models. Sorry for those who use multiple version tables.
|
859
|
-
1. PaperTrail only reifies the first level of associations, i.e., it does not
|
860
|
-
reify any associations of its associations, and so on.
|
861
891
|
1. PaperTrail relies on the callbacks on the association model (and the :through
|
862
892
|
association model for Has-Many-Through associations) to record the versions
|
863
893
|
and the relationship between the versions. If the association is changed
|
@@ -1030,7 +1060,8 @@ Overriding associations is not recommended in general.
|
|
1030
1060
|
### 5.c. Generators
|
1031
1061
|
|
1032
1062
|
PaperTrail has one generator, `paper_trail:install`. It writes, but does not
|
1033
|
-
run, a migration file.
|
1063
|
+
run, a migration file. It also creates a PaperTrail configuration intializer.
|
1064
|
+
The migration adds (at least) the `versions` table. The
|
1034
1065
|
most up-to-date documentation for this generator can be found by running `rails
|
1035
1066
|
generate paper_trail:install --help`, but a copy is included here for
|
1036
1067
|
convenience.
|
@@ -1049,7 +1080,7 @@ Runtime options:
|
|
1049
1080
|
-q, [--quiet], [--no-quiet] # Suppress status output
|
1050
1081
|
-s, [--skip], [--no-skip] # Skip files that already exist
|
1051
1082
|
|
1052
|
-
Generates (but does not run) a migration to add a versions table.
|
1083
|
+
Generates (but does not run) a migration to add a versions table. Also generates an initializer file for configuring PaperTrail
|
1053
1084
|
```
|
1054
1085
|
|
1055
1086
|
## 6. Extensibility
|
@@ -1449,7 +1480,11 @@ require 'paper_trail/frameworks/rspec'
|
|
1449
1480
|
## 8. Sinatra
|
1450
1481
|
|
1451
1482
|
To configure PaperTrail for usage with [Sinatra][12], your `Sinatra`
|
1452
|
-
app must be using `ActiveRecord` 3 or 4.
|
1483
|
+
app must be using `ActiveRecord` 3 or 4. There is no released version of sinatra yet
|
1484
|
+
that is compatible with AR 5. We expect sinatra 2.0 to support AR 5, but it will have
|
1485
|
+
breaking changes that will require changes to PaperTrail.
|
1486
|
+
|
1487
|
+
It is also recommended to use the
|
1453
1488
|
[Sinatra ActiveRecord Extension][13] or something similar for managing your
|
1454
1489
|
applications `ActiveRecord` connection in a manner similar to the way `Rails`
|
1455
1490
|
does. If using the aforementioned `Sinatra ActiveRecord Extension`, steps for
|
@@ -1498,7 +1533,7 @@ end
|
|
1498
1533
|
[Thibault](http://samurails.com/about-me/), 29th September 2014
|
1499
1534
|
* [Versioning with PaperTrail](http://www.sitepoint.com/versioning-papertrail),
|
1500
1535
|
[Ilya Bodrov](http://www.sitepoint.com/author/ibodrov), 10th April 2014
|
1501
|
-
* [Using PaperTrail to track stack traces](http://rubyrailsexpert.com/?p=36),
|
1536
|
+
* [Using PaperTrail to track stack traces](http://web.archive.org/web/20141120233916/http://rubyrailsexpert.com/?p=36),
|
1502
1537
|
T James Corcoran's blog, 1st October 2013.
|
1503
1538
|
* [RailsCast #255 - Undo with PaperTrail](http://railscasts.com/episodes/255-undo-with-paper-trail),
|
1504
1539
|
28th February 2011.
|
data/doc/bug_report_template.rb
CHANGED
@@ -1,19 +1,14 @@
|
|
1
1
|
# Use this template to report PaperTrail bugs.
|
2
|
-
#
|
3
|
-
|
4
|
-
begin
|
5
|
-
require "bundler/inline"
|
6
|
-
rescue LoadError => e
|
7
|
-
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
|
8
|
-
raise e
|
9
|
-
end
|
2
|
+
# Please include only the minimum code necessary to reproduce your issue.
|
3
|
+
require "bundler/inline"
|
10
4
|
|
5
|
+
# STEP ONE: What versions are you using?
|
11
6
|
gemfile(true) do
|
12
|
-
ruby "2.
|
7
|
+
ruby "2.3.1"
|
13
8
|
source "https://rubygems.org"
|
14
|
-
gem "activerecord", "
|
15
|
-
gem "minitest", "5.
|
16
|
-
gem "paper_trail", "
|
9
|
+
gem "activerecord", "5.0.0"
|
10
|
+
gem "minitest", "5.9.0"
|
11
|
+
gem "paper_trail", "5.2.0", require: false
|
17
12
|
gem "sqlite3"
|
18
13
|
end
|
19
14
|
|
@@ -21,13 +16,14 @@ require "active_record"
|
|
21
16
|
require "minitest/autorun"
|
22
17
|
require "logger"
|
23
18
|
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
24
|
-
ActiveRecord::Base.logger =
|
25
|
-
|
19
|
+
ActiveRecord::Base.logger = nil
|
26
20
|
ActiveRecord::Schema.define do
|
21
|
+
# STEP TWO: Define your tables here.
|
27
22
|
create_table :users, force: true do |t|
|
28
23
|
t.text :first_name, null: false
|
29
24
|
t.timestamps null: false
|
30
25
|
end
|
26
|
+
|
31
27
|
create_table :versions do |t|
|
32
28
|
t.string :item_type, null: false
|
33
29
|
t.integer :item_id, null: false
|
@@ -50,18 +46,20 @@ ActiveRecord::Schema.define do
|
|
50
46
|
add_index :version_associations, [:foreign_key_name, :foreign_key_id],
|
51
47
|
name: "index_version_associations_on_foreign_key"
|
52
48
|
end
|
49
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
50
|
+
require "paper_trail/config"
|
51
|
+
|
52
|
+
# STEP THREE: Configure PaperTrail as you would in your initializer
|
53
|
+
PaperTrail::Config.instance.track_associations = true
|
53
54
|
|
54
|
-
# Require `paper_trail.rb` after the `version_associations` table
|
55
|
-
# exists so that PT will track associations.
|
56
55
|
require "paper_trail"
|
57
56
|
|
58
|
-
#
|
59
|
-
# reproduce your issue.
|
57
|
+
# STEP FOUR: Define your AR models here.
|
60
58
|
class User < ActiveRecord::Base
|
61
59
|
has_paper_trail
|
62
60
|
end
|
63
61
|
|
64
|
-
# Please write a test that demonstrates your issue
|
62
|
+
# STEP FIVE: Please write a test that demonstrates your issue.
|
65
63
|
class BugTest < ActiveSupport::TestCase
|
66
64
|
def test_1
|
67
65
|
assert_difference(-> { PaperTrail::Version.count }, +1) {
|
data/gemfiles/ar3.gemfile
CHANGED
data/gemfiles/ar4.gemfile
CHANGED
data/gemfiles/ar5.gemfile
CHANGED
@@ -2,12 +2,8 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem "activerecord", "5.0.0
|
6
|
-
gem "
|
7
|
-
gem "actionpack", "5.0.0.beta3"
|
8
|
-
gem "railties", "5.0.0.beta3"
|
9
|
-
gem "rspec-rails", "3.5.0.beta3"
|
5
|
+
gem "activerecord", "~> 5.0.0"
|
6
|
+
gem "rspec-rails", "~> 3.5.1"
|
10
7
|
gem "rails-controller-testing"
|
11
|
-
gem "sinatra", :github => "sinatra/sinatra"
|
12
8
|
|
13
9
|
gemspec :path => "../"
|
File without changes
|
@@ -20,7 +20,8 @@ module PaperTrail
|
|
20
20
|
desc: "Store transactional IDs to support association restoration"
|
21
21
|
)
|
22
22
|
|
23
|
-
desc "Generates (but does not run) a migration to add a versions table."
|
23
|
+
desc "Generates (but does not run) a migration to add a versions table." \
|
24
|
+
" Also generates an initializer file for configuring PaperTrail"
|
24
25
|
|
25
26
|
def create_migration_file
|
26
27
|
add_paper_trail_migration("create_versions")
|
@@ -31,6 +32,13 @@ module PaperTrail
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
def create_initializer
|
36
|
+
create_file(
|
37
|
+
"config/initializers/paper_trail.rb",
|
38
|
+
"PaperTrail.config.track_associations = #{!!options.with_associations?}"
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
34
42
|
def self.next_migration_number(dirname)
|
35
43
|
::ActiveRecord::Generators::Base.next_migration_number(dirname)
|
36
44
|
end
|
@@ -8,19 +8,41 @@ module PaperTrail
|
|
8
8
|
# This implementation depends on the `type_for_attribute` method, which was
|
9
9
|
# introduced in rails 4.2. In older versions of rails, we shim this method
|
10
10
|
# with `LegacyActiveRecordShim`.
|
11
|
+
class CastAttributeSerializer
|
12
|
+
def initialize(klass)
|
13
|
+
@klass = klass
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Returns a hash mapping attributes to hashes that map strings to
|
19
|
+
# integers. Example:
|
20
|
+
#
|
21
|
+
# ```
|
22
|
+
# { "status" => { "draft"=>0, "published"=>1, "archived"=>2 } }
|
23
|
+
# ```
|
24
|
+
#
|
25
|
+
# ActiveRecord::Enum was added in AR 4.1
|
26
|
+
# http://edgeguides.rubyonrails.org/4_1_release_notes.html#active-record-enums
|
27
|
+
def defined_enums
|
28
|
+
@defined_enums ||= (@klass.respond_to?(:defined_enums) ? @klass.defined_enums : {})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
11
32
|
if ::ActiveRecord::VERSION::MAJOR >= 5
|
12
33
|
# This implementation uses AR 5's `serialize` and `deserialize`.
|
13
34
|
class CastAttributeSerializer
|
14
|
-
def initialize(klass)
|
15
|
-
@klass = klass
|
16
|
-
end
|
17
|
-
|
18
35
|
def serialize(attr, val)
|
19
36
|
@klass.type_for_attribute(attr).serialize(val)
|
20
37
|
end
|
21
38
|
|
22
39
|
def deserialize(attr, val)
|
23
|
-
|
40
|
+
if defined_enums[attr] && val.is_a?(::String)
|
41
|
+
# Because PT 4 used to save the string version of enums to `object_changes`
|
42
|
+
val
|
43
|
+
else
|
44
|
+
@klass.type_for_attribute(attr).deserialize(val)
|
45
|
+
end
|
24
46
|
end
|
25
47
|
end
|
26
48
|
else
|
@@ -29,29 +51,29 @@ module PaperTrail
|
|
29
51
|
# `type_cast_for_database` in our shim attribute type classes,
|
30
52
|
# `NoOpAttribute` and `SerializedAttribute`.
|
31
53
|
class CastAttributeSerializer
|
32
|
-
def initialize(klass)
|
33
|
-
@klass = klass
|
34
|
-
end
|
35
|
-
|
36
54
|
def serialize(attr, val)
|
37
|
-
|
38
|
-
|
55
|
+
castable_val = val
|
56
|
+
if defined_enums[attr]
|
57
|
+
# `attr` is an enum. Find the number that corresponds to `val`. If `val` is
|
58
|
+
# a number already, there won't be a corresponding entry, just use `val`.
|
59
|
+
castable_val = defined_enums[attr][val] || val
|
60
|
+
end
|
61
|
+
@klass.type_for_attribute(attr).type_cast_for_database(castable_val)
|
39
62
|
end
|
40
63
|
|
41
64
|
def deserialize(attr, val)
|
42
|
-
|
43
|
-
|
44
|
-
defined_enums[attr].key(val)
|
45
|
-
else
|
65
|
+
if defined_enums[attr] && val.is_a?(::String)
|
66
|
+
# Because PT 4 used to save the string version of enums to `object_changes`
|
46
67
|
val
|
68
|
+
else
|
69
|
+
val = @klass.type_for_attribute(attr).type_cast_from_database(val)
|
70
|
+
if defined_enums[attr]
|
71
|
+
defined_enums[attr].key(val)
|
72
|
+
else
|
73
|
+
val
|
74
|
+
end
|
47
75
|
end
|
48
76
|
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def defined_enums
|
53
|
-
@defined_enums ||= (@klass.respond_to?(:defined_enums) ? @klass.defined_enums : {})
|
54
|
-
end
|
55
77
|
end
|
56
78
|
end
|
57
79
|
end
|
@@ -94,6 +94,11 @@ module PaperTrail
|
|
94
94
|
::ActiveRecord::Base.belongs_to_required_by_default
|
95
95
|
end
|
96
96
|
|
97
|
+
def habtm_assocs_not_skipped
|
98
|
+
@model_class.reflect_on_all_associations(:has_and_belongs_to_many).
|
99
|
+
reject { |a| @model_class.paper_trail_options[:skip].include?(a.name.to_s) }
|
100
|
+
end
|
101
|
+
|
97
102
|
def setup_associations(options)
|
98
103
|
@model_class.class_attribute :version_association_name
|
99
104
|
@model_class.version_association_name = options[:version] || :version
|
@@ -122,7 +127,7 @@ module PaperTrail
|
|
122
127
|
@model_class.versions_association_name,
|
123
128
|
class_name: @model_class.version_class_name,
|
124
129
|
as: :item,
|
125
|
-
order: @model_class.
|
130
|
+
order: @model_class.paper_trail.version_class.timestamp_sort_order
|
126
131
|
)
|
127
132
|
end
|
128
133
|
end
|
@@ -133,18 +138,7 @@ module PaperTrail
|
|
133
138
|
@model_class.send :attr_accessor, :paper_trail_habtm
|
134
139
|
@model_class.class_attribute :paper_trail_save_join_tables
|
135
140
|
@model_class.paper_trail_save_join_tables = Array.wrap(join_tables)
|
136
|
-
|
137
|
-
reject { |a| @model_class.paper_trail_options[:skip].include?(a.name.to_s) }.
|
138
|
-
each { |a|
|
139
|
-
added_callback = lambda do |*args|
|
140
|
-
update_habtm_state(a.name, :before_add, args[-2], args.last)
|
141
|
-
end
|
142
|
-
removed_callback = lambda do |*args|
|
143
|
-
update_habtm_state(a.name, :before_remove, args[-2], args.last)
|
144
|
-
end
|
145
|
-
@model_class.send(:"before_add_for_#{a.name}").send(:<<, added_callback)
|
146
|
-
@model_class.send(:"before_remove_for_#{a.name}").send(:<<, removed_callback)
|
147
|
-
}
|
141
|
+
habtm_assocs_not_skipped.each(&method(:setup_habtm_change_callbacks))
|
148
142
|
end
|
149
143
|
|
150
144
|
def setup_callbacks_from_options(options_on = [])
|
@@ -153,6 +147,18 @@ module PaperTrail
|
|
153
147
|
end
|
154
148
|
end
|
155
149
|
|
150
|
+
def setup_habtm_change_callbacks(assoc)
|
151
|
+
assoc_name = assoc.name
|
152
|
+
%w(add remove).each do |verb|
|
153
|
+
@model_class.send(:"before_#{verb}_for_#{assoc_name}").send(
|
154
|
+
:<<,
|
155
|
+
lambda do |*args|
|
156
|
+
update_habtm_state(assoc_name, :"before_#{verb}", args[-2], args.last)
|
157
|
+
end
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
156
162
|
def setup_options(options)
|
157
163
|
@model_class.class_attribute :paper_trail_options
|
158
164
|
@model_class.paper_trail_options = options.dup
|
@@ -179,14 +185,16 @@ module PaperTrail
|
|
179
185
|
|
180
186
|
def update_habtm_state(name, callback, model, assoc)
|
181
187
|
model.paper_trail_habtm ||= {}
|
182
|
-
model.paper_trail_habtm
|
188
|
+
model.paper_trail_habtm[name] ||= { removed: [], added: [] }
|
189
|
+
state = model.paper_trail_habtm[name]
|
190
|
+
assoc_id = assoc.id
|
183
191
|
case callback
|
184
192
|
when :before_add
|
185
|
-
|
186
|
-
|
193
|
+
state[:added] |= [assoc_id]
|
194
|
+
state[:removed] -= [assoc_id]
|
187
195
|
when :before_remove
|
188
|
-
|
189
|
-
|
196
|
+
state[:removed] |= [assoc_id]
|
197
|
+
state[:added] -= [assoc_id]
|
190
198
|
else
|
191
199
|
raise "Invalid callback: #{callback}"
|
192
200
|
end
|
data/paper_trail.gemspec
CHANGED
@@ -3,7 +3,7 @@ require "paper_trail/version_number"
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "paper_trail"
|
6
|
-
s.version = PaperTrail::VERSION::STRING
|
6
|
+
s.version = PaperTrail::VERSION::STRING.dup # The `dup` is for ruby 1.9.3
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.summary = "Track changes to your models' data. Good for auditing or versioning."
|
9
9
|
s.description = s.summary
|
@@ -29,13 +29,12 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_development_dependency "shoulda", "~> 3.5.0"
|
30
30
|
s.add_development_dependency "ffaker", "~> 2.1.0"
|
31
31
|
s.add_development_dependency "railties", [">= 3.0", "< 6.0"]
|
32
|
-
s.add_development_dependency "sinatra", "~> 1.4.6"
|
33
32
|
s.add_development_dependency "rack-test", "~> 0.6.3"
|
34
|
-
s.add_development_dependency "rspec-rails", "~> 3.
|
33
|
+
s.add_development_dependency "rspec-rails", "~> 3.5"
|
35
34
|
s.add_development_dependency "generator_spec", "~> 0.9.3"
|
36
35
|
s.add_development_dependency "database_cleaner", "~> 1.2"
|
37
36
|
s.add_development_dependency "pry-nav", "~> 0.2.4"
|
38
|
-
s.add_development_dependency "rubocop", "~> 0.
|
37
|
+
s.add_development_dependency "rubocop", "~> 0.41.1"
|
39
38
|
s.add_development_dependency "timecop", "~> 0.8.0"
|
40
39
|
|
41
40
|
if defined?(JRUBY_VERSION)
|
data/spec/models/gadget_spec.rb
CHANGED
@@ -25,7 +25,7 @@ describe Gadget, type: :model do
|
|
25
25
|
describe "Methods" do
|
26
26
|
describe "Instance", versioning: true do
|
27
27
|
describe "private" do
|
28
|
-
describe
|
28
|
+
describe "#changed_notably?" do
|
29
29
|
subject { Gadget.new(created_at: Time.now) }
|
30
30
|
|
31
31
|
context "create events" do
|
@@ -14,19 +14,19 @@ describe JoinedVersion, type: :model, versioning: true do
|
|
14
14
|
describe "VersionConcern::ClassMethods" do
|
15
15
|
before { widget } # persist a widget
|
16
16
|
|
17
|
-
describe
|
17
|
+
describe "#subsequent" do
|
18
18
|
it "shouldn't error out when there is a default_scope that joins" do
|
19
19
|
JoinedVersion.subsequent(version).first
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
describe
|
23
|
+
describe "#preceding" do
|
24
24
|
it "shouldn't error out when there is a default scope that joins" do
|
25
25
|
JoinedVersion.preceding(version).first
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
describe
|
29
|
+
describe "#between" do
|
30
30
|
it "shouldn't error out when there is a default scope that joins" do
|
31
31
|
JoinedVersion.between(Time.now, 1.minute.from_now).first
|
32
32
|
end
|
@@ -35,7 +35,7 @@ describe JoinedVersion, type: :model, versioning: true do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
describe "Methods" do
|
38
|
-
describe
|
38
|
+
describe "#index" do
|
39
39
|
it { is_expected.to respond_to(:index) }
|
40
40
|
|
41
41
|
it "shouldn't error out when there is a default scope that joins" do
|
@@ -11,7 +11,7 @@ if JsonVersion.table_exists?
|
|
11
11
|
|
12
12
|
describe "Methods" do
|
13
13
|
describe "Class" do
|
14
|
-
describe
|
14
|
+
describe "#where_object" do
|
15
15
|
it { expect(JsonVersion).to respond_to(:where_object) }
|
16
16
|
|
17
17
|
it "escapes values" do
|
@@ -50,7 +50,7 @@ if JsonVersion.table_exists?
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe
|
53
|
+
describe "#where_object_changes" do
|
54
54
|
it { expect(JsonVersion).to respond_to(:where_object_changes) }
|
55
55
|
|
56
56
|
it "escapes values" do
|
@@ -4,7 +4,7 @@ module Kitchen
|
|
4
4
|
describe Banana, type: :model do
|
5
5
|
it { is_expected.to be_versioned }
|
6
6
|
|
7
|
-
describe
|
7
|
+
describe "#versions" do
|
8
8
|
it "returns instances of Kitchen::BananaVersion", versioning: true do
|
9
9
|
banana = described_class.create!
|
10
10
|
expect(banana.versions.first).to be_a(Kitchen::BananaVersion)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "rails_helper"
|
2
2
|
|
3
|
-
# This model
|
4
|
-
#
|
3
|
+
# This model tests ActiveRecord::Enum, which was added in AR 4.1
|
4
|
+
# http://edgeguides.rubyonrails.org/4_1_release_notes.html#active-record-enums
|
5
5
|
describe PostWithStatus, type: :model do
|
6
6
|
if defined?(ActiveRecord::Enum)
|
7
7
|
with_versioning do
|
8
|
-
let(:post) {
|
8
|
+
let(:post) { described_class.create!(status: "draft") }
|
9
9
|
|
10
10
|
it "should stash the enum value properly in versions" do
|
11
11
|
post.published!
|
@@ -13,6 +13,16 @@ describe PostWithStatus, type: :model do
|
|
13
13
|
expect(post.paper_trail.previous_version.published?).to be true
|
14
14
|
end
|
15
15
|
|
16
|
+
it "can read enums in version records written by PT 4" do
|
17
|
+
post = described_class.create(status: "draft")
|
18
|
+
post.published!
|
19
|
+
version = post.versions.last
|
20
|
+
# Simulate behavior PT 4, which used to save the string version of
|
21
|
+
# enums to `object_changes`
|
22
|
+
version.update(object_changes: "---\nid:\n- \n- 1\nstatus:\n- draft\n- published\n")
|
23
|
+
assert_equal %w(draft published), version.changeset["status"]
|
24
|
+
end
|
25
|
+
|
16
26
|
context "storing enum object_changes" do
|
17
27
|
subject { post.versions.last }
|
18
28
|
|
@@ -22,6 +32,19 @@ describe PostWithStatus, type: :model do
|
|
22
32
|
expect(subject.changeset["status"]).to eql %w(published archived)
|
23
33
|
end
|
24
34
|
end
|
35
|
+
|
36
|
+
describe "#touch_with_version" do
|
37
|
+
it "preserves the enum value (and all other attributes)" do
|
38
|
+
post = described_class.create(status: :draft)
|
39
|
+
expect(post.versions.count).to eq(1)
|
40
|
+
expect(post.status).to eq("draft")
|
41
|
+
Timecop.travel 1.second.since # because MySQL lacks fractional seconds precision
|
42
|
+
post.paper_trail.touch_with_version
|
43
|
+
expect(post.versions.count).to eq(2)
|
44
|
+
expect(post.versions.last[:object]).to include("status: 0")
|
45
|
+
expect(post.paper_trail.previous_version.status).to eq("draft")
|
46
|
+
end
|
47
|
+
end
|
25
48
|
end
|
26
49
|
end
|
27
50
|
end
|
data/spec/models/version_spec.rb
CHANGED
@@ -6,13 +6,6 @@ describe PaperTrail::Version, type: :model do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
describe "Attributes" do
|
9
|
-
it { is_expected.to have_db_column(:item_type).of_type(:string) }
|
10
|
-
it { is_expected.to have_db_column(:item_id).of_type(:integer) }
|
11
|
-
it { is_expected.to have_db_column(:event).of_type(:string) }
|
12
|
-
it { is_expected.to have_db_column(:whodunnit).of_type(:string) }
|
13
|
-
it { is_expected.to have_db_column(:object).of_type(:text) }
|
14
|
-
it { is_expected.to have_db_column(:created_at).of_type(:datetime) }
|
15
|
-
|
16
9
|
describe "object_changes column", versioning: true do
|
17
10
|
let(:widget) { Widget.create!(name: "Dashboard") }
|
18
11
|
let(:value) { widget.versions.last.object_changes }
|
@@ -37,15 +30,11 @@ describe PaperTrail::Version, type: :model do
|
|
37
30
|
end
|
38
31
|
end
|
39
32
|
|
40
|
-
describe "Indexes" do
|
41
|
-
it { is_expected.to have_db_index([:item_type, :item_id]) }
|
42
|
-
end
|
43
|
-
|
44
33
|
describe "Methods" do
|
45
34
|
describe "Instance" do
|
46
35
|
subject { PaperTrail::Version.new }
|
47
36
|
|
48
|
-
describe
|
37
|
+
describe "#paper_trail_originator" do
|
49
38
|
it { is_expected.to respond_to(:paper_trail_originator) }
|
50
39
|
|
51
40
|
context "No previous versions" do
|
@@ -89,7 +78,7 @@ describe PaperTrail::Version, type: :model do
|
|
89
78
|
end
|
90
79
|
end
|
91
80
|
|
92
|
-
describe
|
81
|
+
describe "#terminator" do
|
93
82
|
let(:attributes) { { whodunnit: FFaker::Name.first_name } }
|
94
83
|
subject { PaperTrail::Version.new attributes }
|
95
84
|
|
@@ -100,7 +89,7 @@ describe PaperTrail::Version, type: :model do
|
|
100
89
|
end
|
101
90
|
end
|
102
91
|
|
103
|
-
describe
|
92
|
+
describe "#version_author" do
|
104
93
|
it { is_expected.to respond_to(:version_author) }
|
105
94
|
|
106
95
|
it "should be an alias for the `terminator` method" do
|
@@ -140,7 +129,7 @@ describe PaperTrail::Version, type: :model do
|
|
140
129
|
end
|
141
130
|
end
|
142
131
|
|
143
|
-
describe
|
132
|
+
describe "#where_object" do
|
144
133
|
it { expect(PaperTrail::Version).to respond_to(:where_object) }
|
145
134
|
|
146
135
|
context "invalid arguments" do
|
@@ -205,7 +194,7 @@ describe PaperTrail::Version, type: :model do
|
|
205
194
|
end
|
206
195
|
end
|
207
196
|
|
208
|
-
describe
|
197
|
+
describe "#where_object_changes" do
|
209
198
|
context "invalid arguments" do
|
210
199
|
it "should raise an error" do
|
211
200
|
expect {
|
data/spec/models/widget_spec.rb
CHANGED
@@ -140,7 +140,42 @@ describe Widget, type: :model do
|
|
140
140
|
|
141
141
|
describe "Methods" do
|
142
142
|
describe "Instance", versioning: true do
|
143
|
-
describe
|
143
|
+
describe "#create" do
|
144
|
+
it "creates a version record" do
|
145
|
+
wordget = Widget.create
|
146
|
+
assert_equal 1, wordget.versions.length
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "#destroy" do
|
151
|
+
it "creates a version record" do
|
152
|
+
widget = Widget.create
|
153
|
+
assert_equal 1, widget.versions.length
|
154
|
+
widget.destroy
|
155
|
+
versions_for_widget = PaperTrail::Version.with_item_keys("Widget", widget.id)
|
156
|
+
assert_equal 2, versions_for_widget.length
|
157
|
+
end
|
158
|
+
|
159
|
+
it "can have multiple destruction records" do
|
160
|
+
versions = lambda { |widget|
|
161
|
+
# Workaround for AR 3. When we drop AR 3 support, we can simply use
|
162
|
+
# the `widget.versions` association, instead of `with_item_keys`.
|
163
|
+
PaperTrail::Version.with_item_keys("Widget", widget.id)
|
164
|
+
}
|
165
|
+
widget = Widget.create
|
166
|
+
assert_equal 1, widget.versions.length
|
167
|
+
widget.destroy
|
168
|
+
assert_equal 2, versions.call(widget).length
|
169
|
+
widget = widget.version.reify
|
170
|
+
widget.save
|
171
|
+
assert_equal 3, versions.call(widget).length
|
172
|
+
widget.destroy
|
173
|
+
assert_equal 4, versions.call(widget).length
|
174
|
+
assert_equal 2, versions.call(widget).where(event: "destroy").length
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "#paper_trail.originator" do
|
144
179
|
describe "return value" do
|
145
180
|
let(:orig_name) { FFaker::Name.name }
|
146
181
|
let(:new_name) { FFaker::Name.name }
|
@@ -192,7 +227,7 @@ describe Widget, type: :model do
|
|
192
227
|
end
|
193
228
|
end
|
194
229
|
|
195
|
-
describe
|
230
|
+
describe "#version_at" do
|
196
231
|
context "Timestamp argument is AFTER object has been destroyed" do
|
197
232
|
it "should return `nil`" do
|
198
233
|
widget.update_attribute(:name, "foobar")
|
@@ -202,7 +237,7 @@ describe Widget, type: :model do
|
|
202
237
|
end
|
203
238
|
end
|
204
239
|
|
205
|
-
describe
|
240
|
+
describe "#whodunnit" do
|
206
241
|
it { is_expected.to respond_to(:whodunnit) }
|
207
242
|
|
208
243
|
context "no block given" do
|
@@ -250,7 +285,7 @@ describe Widget, type: :model do
|
|
250
285
|
end
|
251
286
|
end
|
252
287
|
|
253
|
-
describe
|
288
|
+
describe "#touch_with_version" do
|
254
289
|
it "creates a version" do
|
255
290
|
count = widget.versions.size
|
256
291
|
# Travel 1 second because MySQL lacks sub-second resolution
|
@@ -269,6 +304,15 @@ describe Widget, type: :model do
|
|
269
304
|
expect(widget.updated_at).to be > time_was
|
270
305
|
end
|
271
306
|
end
|
307
|
+
|
308
|
+
describe "#update" do
|
309
|
+
it "creates a version record" do
|
310
|
+
widget = Widget.create
|
311
|
+
assert_equal 1, widget.versions.length
|
312
|
+
widget.update_attributes(name: "Bugle")
|
313
|
+
assert_equal 2, widget.versions.length
|
314
|
+
end
|
315
|
+
end
|
272
316
|
end
|
273
317
|
|
274
318
|
describe "Class" do
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "rails_helper"
|
2
2
|
|
3
3
|
describe PaperTrail, type: :module, versioning: true do
|
4
|
-
describe
|
4
|
+
describe "#config" do
|
5
5
|
it { is_expected.to respond_to(:config) }
|
6
6
|
|
7
7
|
it "should allow for config values to be set" do
|
@@ -17,7 +17,7 @@ describe PaperTrail, type: :module, versioning: true do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
describe
|
20
|
+
describe "#configure" do
|
21
21
|
it { is_expected.to respond_to(:configure) }
|
22
22
|
|
23
23
|
it "should be an alias for the `config` method" do
|
data/spec/paper_trail_spec.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
require "rails_helper"
|
2
2
|
|
3
3
|
describe PaperTrail do
|
4
|
+
context "when enabled" do
|
5
|
+
it "affects all threads" do
|
6
|
+
Thread.new { PaperTrail.enabled = false }.join
|
7
|
+
assert_equal false, PaperTrail.enabled?
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
PaperTrail.enabled = true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
context "default" do
|
5
16
|
it "should have versioning off by default" do
|
6
17
|
expect(PaperTrail).not_to be_enabled
|
data/spec/rails_helper.rb
CHANGED
data/test/dummy/db/schema.rb
CHANGED
@@ -162,7 +162,9 @@ ActiveRecord::Schema.define(version: 20110208155312) do
|
|
162
162
|
add_index "post_versions", ["item_type", "item_id"], name: "index_post_versions_on_item_type_and_item_id"
|
163
163
|
|
164
164
|
create_table "post_with_statuses", force: :cascade do |t|
|
165
|
-
t.integer
|
165
|
+
t.integer "status"
|
166
|
+
t.datetime "created_at", null: false
|
167
|
+
t.datetime "updated_at", null: false
|
166
168
|
end
|
167
169
|
|
168
170
|
create_table "posts", force: :cascade do |t|
|
@@ -1,11 +1,4 @@
|
|
1
|
-
#
|
2
|
-
# which renames several files that sinatra 1 depended on. Until there is
|
3
|
-
# a released version of sinatra that supports `rack 2.0.0.alpha`, we
|
4
|
-
# must exclude sinatra from our test suite. This is done in two files:
|
5
|
-
#
|
6
|
-
# - test/functional/sinatra_test.rb
|
7
|
-
# - test/functional/modular_sinatra_test.rb
|
8
|
-
#
|
1
|
+
# PaperTrail is not compatible with sinatra 2 yet. Contributions welcome.
|
9
2
|
if Gem::Version.new(Rack.release) < Gem::Version.new("2.0.0.alpha")
|
10
3
|
require "test_helper"
|
11
4
|
require "sinatra/base"
|
@@ -1,11 +1,4 @@
|
|
1
|
-
#
|
2
|
-
# which renames several files that sinatra 1 depended on. Until there is
|
3
|
-
# a released version of sinatra that supports `rack 2.0.0.alpha`, we
|
4
|
-
# must exclude sinatra from our test suite. This is done in two files:
|
5
|
-
#
|
6
|
-
# - test/functional/sinatra_test.rb
|
7
|
-
# - test/functional/modular_sinatra_test.rb
|
8
|
-
#
|
1
|
+
# PaperTrail is not compatible with sinatra 2 yet. Contributions welcome.
|
9
2
|
if Gem::Version.new(Rack.release) < Gem::Version.new("2.0.0.alpha")
|
10
3
|
require "test_helper"
|
11
4
|
# require 'sinatra/main'
|
data/test/unit/model_test.rb
CHANGED
@@ -943,7 +943,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
943
943
|
context "A reified item" do
|
944
944
|
setup do
|
945
945
|
widget = Widget.create name: "Bob"
|
946
|
-
%w(
|
946
|
+
%w(Tom Dick Jane).each { |name| widget.update_attributes name: name }
|
947
947
|
@version = widget.versions.last
|
948
948
|
@widget = @version.reify
|
949
949
|
end
|
@@ -972,7 +972,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
972
972
|
context "with versions" do
|
973
973
|
setup do
|
974
974
|
@widget.save
|
975
|
-
%w(
|
975
|
+
%w(Tom Dick Jane).each { |name| @widget.update_attributes name: name }
|
976
976
|
end
|
977
977
|
|
978
978
|
should "have a previous version" do
|
@@ -1405,7 +1405,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
1405
1405
|
context "A reified item with a column -version- and custom version_method" do
|
1406
1406
|
setup do
|
1407
1407
|
widget = LegacyWidget.create(name: "foo", version: 2)
|
1408
|
-
%w(
|
1408
|
+
%w(bar baz).each { |name| widget.update_attributes name: name }
|
1409
1409
|
@version = widget.versions.last
|
1410
1410
|
@widget = @version.reify
|
1411
1411
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paper_trail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.2.
|
4
|
+
version: 5.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Stewart
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-09-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -141,20 +141,6 @@ dependencies:
|
|
141
141
|
- - "<"
|
142
142
|
- !ruby/object:Gem::Version
|
143
143
|
version: '6.0'
|
144
|
-
- !ruby/object:Gem::Dependency
|
145
|
-
name: sinatra
|
146
|
-
requirement: !ruby/object:Gem::Requirement
|
147
|
-
requirements:
|
148
|
-
- - "~>"
|
149
|
-
- !ruby/object:Gem::Version
|
150
|
-
version: 1.4.6
|
151
|
-
type: :development
|
152
|
-
prerelease: false
|
153
|
-
version_requirements: !ruby/object:Gem::Requirement
|
154
|
-
requirements:
|
155
|
-
- - "~>"
|
156
|
-
- !ruby/object:Gem::Version
|
157
|
-
version: 1.4.6
|
158
144
|
- !ruby/object:Gem::Dependency
|
159
145
|
name: rack-test
|
160
146
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,14 +161,14 @@ dependencies:
|
|
175
161
|
requirements:
|
176
162
|
- - "~>"
|
177
163
|
- !ruby/object:Gem::Version
|
178
|
-
version: 3.
|
164
|
+
version: '3.5'
|
179
165
|
type: :development
|
180
166
|
prerelease: false
|
181
167
|
version_requirements: !ruby/object:Gem::Requirement
|
182
168
|
requirements:
|
183
169
|
- - "~>"
|
184
170
|
- !ruby/object:Gem::Version
|
185
|
-
version: 3.
|
171
|
+
version: '3.5'
|
186
172
|
- !ruby/object:Gem::Dependency
|
187
173
|
name: generator_spec
|
188
174
|
requirement: !ruby/object:Gem::Requirement
|
@@ -231,14 +217,14 @@ dependencies:
|
|
231
217
|
requirements:
|
232
218
|
- - "~>"
|
233
219
|
- !ruby/object:Gem::Version
|
234
|
-
version: 0.
|
220
|
+
version: 0.41.1
|
235
221
|
type: :development
|
236
222
|
prerelease: false
|
237
223
|
version_requirements: !ruby/object:Gem::Requirement
|
238
224
|
requirements:
|
239
225
|
- - "~>"
|
240
226
|
- !ruby/object:Gem::Version
|
241
|
-
version: 0.
|
227
|
+
version: 0.41.1
|
242
228
|
- !ruby/object:Gem::Dependency
|
243
229
|
name: timecop
|
244
230
|
requirement: !ruby/object:Gem::Requirement
|
@@ -320,6 +306,7 @@ files:
|
|
320
306
|
- gemfiles/ar4.gemfile
|
321
307
|
- gemfiles/ar5.gemfile
|
322
308
|
- lib/generators/paper_trail/USAGE
|
309
|
+
- lib/generators/paper_trail/default_initializer.rb
|
323
310
|
- lib/generators/paper_trail/install_generator.rb
|
324
311
|
- lib/generators/paper_trail/templates/add_object_changes_to_versions.rb
|
325
312
|
- lib/generators/paper_trail/templates/add_transaction_id_column_to_versions.rb
|
@@ -463,7 +450,6 @@ files:
|
|
463
450
|
- test/functional/modular_sinatra_test.rb
|
464
451
|
- test/functional/sinatra_test.rb
|
465
452
|
- test/functional/thread_safety_test.rb
|
466
|
-
- test/paper_trail_test.rb
|
467
453
|
- test/test_helper.rb
|
468
454
|
- test/time_travel_helper.rb
|
469
455
|
- test/unit/associations_test.rb
|
@@ -612,7 +598,6 @@ test_files:
|
|
612
598
|
- test/functional/modular_sinatra_test.rb
|
613
599
|
- test/functional/sinatra_test.rb
|
614
600
|
- test/functional/thread_safety_test.rb
|
615
|
-
- test/paper_trail_test.rb
|
616
601
|
- test/test_helper.rb
|
617
602
|
- test/time_travel_helper.rb
|
618
603
|
- test/unit/associations_test.rb
|
data/test/paper_trail_test.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class PaperTrailTest < ActiveSupport::TestCase
|
4
|
-
test "Sanity test" do
|
5
|
-
assert_kind_of Module, PaperTrail::Version
|
6
|
-
end
|
7
|
-
|
8
|
-
test "Version Number" do
|
9
|
-
assert PaperTrail.const_defined?(:VERSION)
|
10
|
-
end
|
11
|
-
|
12
|
-
context "setting enabled" do
|
13
|
-
should "affect all threads" do
|
14
|
-
Thread.new { PaperTrail.enabled = false }.join
|
15
|
-
assert_equal false, PaperTrail.enabled?
|
16
|
-
end
|
17
|
-
teardown { PaperTrail.enabled = true }
|
18
|
-
end
|
19
|
-
|
20
|
-
test "create with plain model class" do
|
21
|
-
widget = Widget.create
|
22
|
-
assert_equal 1, widget.versions.length
|
23
|
-
end
|
24
|
-
|
25
|
-
test "update with plain model class" do
|
26
|
-
widget = Widget.create
|
27
|
-
assert_equal 1, widget.versions.length
|
28
|
-
widget.update_attributes(name: "Bugle")
|
29
|
-
assert_equal 2, widget.versions.length
|
30
|
-
end
|
31
|
-
|
32
|
-
test "destroy with plain model class" do
|
33
|
-
widget = Widget.create
|
34
|
-
assert_equal 1, widget.versions.length
|
35
|
-
widget.destroy
|
36
|
-
versions_for_widget = PaperTrail::Version.with_item_keys("Widget", widget.id)
|
37
|
-
assert_equal 2, versions_for_widget.length
|
38
|
-
end
|
39
|
-
end
|