paper_trail 5.2.0 → 5.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|