paper_trail 4.0.0 → 4.0.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/CHANGELOG.md +22 -7
- data/CONTRIBUTING.md +11 -0
- data/README.md +260 -229
- data/lib/paper_trail.rb +17 -13
- data/lib/paper_trail/cleaner.rb +21 -11
- data/lib/paper_trail/config.rb +3 -1
- data/lib/paper_trail/frameworks/active_record.rb +2 -2
- data/lib/paper_trail/frameworks/rails/controller.rb +11 -9
- data/lib/paper_trail/frameworks/sinatra.rb +2 -1
- data/lib/paper_trail/has_paper_trail.rb +90 -54
- data/lib/paper_trail/version_concern.rb +87 -58
- data/lib/paper_trail/version_number.rb +1 -1
- data/spec/models/skipper_spec.rb +38 -9
- data/spec/models/widget_spec.rb +2 -2
- data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +2 -1
- data/test/dummy/db/schema.rb +63 -25
- data/test/unit/model_test.rb +2 -2
- metadata +47 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 047fe27b3f2154c19030502f4d129dcdd2873146
|
4
|
+
data.tar.gz: 6b6f268b260b459e0e6df8340ec9d33cb5c07824
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49c10975deb4b0f20617b4b770a1f6b99d2980df4072dd71da1dc48c7da85e409c6eeadcbfcc74f86f239b320e7ae73f6d7d2f72971439a39330d6f353b9f33e
|
7
|
+
data.tar.gz: 3ecddc1755c7d139e04716582bbe136163605eb33354acaf7e520bc0178dfe7c9d184c8f673f4bb744440c4e7113a58017c6de4fca9262ff99575bee764d804d
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 4.0.1
|
2
|
+
|
3
|
+
### Breaking Changes
|
4
|
+
|
5
|
+
- None
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- None
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
- [#636](https://github.com/airblade/paper_trail/issues/636) -
|
14
|
+
Should compile assets without a db connection
|
15
|
+
- [#589](https://github.com/airblade/paper_trail/pull/589) /
|
16
|
+
[#588](https://github.com/airblade/paper_trail/issues/588) -
|
17
|
+
Fixes timestamp for "create" versions
|
18
|
+
|
1
19
|
## 4.0.0
|
2
20
|
|
3
21
|
This major release adds JSON column support in PostgreSQL, limited support for
|
@@ -5,7 +23,7 @@ versioning associations, various new configuration options, and a year's worth
|
|
5
23
|
of bug fixes. Thanks to everyone who helped test the two betas and two release
|
6
24
|
candidates.
|
7
25
|
|
8
|
-
###
|
26
|
+
### Breaking Changes
|
9
27
|
|
10
28
|
- Using a Rails initializer to reopen PaperTrail::Version or otherwise extend
|
11
29
|
PaperTrail is no longer recommended. An alternative is described in the
|
@@ -13,6 +31,9 @@ candidates.
|
|
13
31
|
https://github.com/airblade/paper_trail/pull/492.
|
14
32
|
- If you depend on the `RSpec` or `Cucumber` helpers, you must
|
15
33
|
[require them in your test helper](https://github.com/airblade/paper_trail#testing).
|
34
|
+
- [#566](https://github.com/airblade/paper_trail/pull/566) - Removed deprecated
|
35
|
+
methods `paper_trail_on` and `paper_trail_off`. Use `paper_trail_on!` and
|
36
|
+
`paper_trail_off!` instead.
|
16
37
|
- [#458](https://github.com/airblade/paper_trail/pull/458) - Version metadata
|
17
38
|
(the `:meta` option) from AR attributes for `create` events will now save the
|
18
39
|
current value instead of `nil`.
|
@@ -29,12 +50,6 @@ candidates.
|
|
29
50
|
- `3da1f104` - `PaperTrail.config` and `PaperTrail.configure` are now
|
30
51
|
identical: both return the `PaperTrail::Config` instance and also
|
31
52
|
yield it if a block is provided.
|
32
|
-
|
33
|
-
### Removed
|
34
|
-
|
35
|
-
- [#566](https://github.com/airblade/paper_trail/pull/566) - Removed deprecated
|
36
|
-
methods `paper_trail_on` and `paper_trail_off`. Use `paper_trail_on!` and
|
37
|
-
`paper_trail_off!` instead.
|
38
53
|
|
39
54
|
### Added
|
40
55
|
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
Thanks for your interest in PaperTrail! We appreciate bug reports, feature
|
4
|
+
suggestions, and especially pull requests.
|
5
|
+
|
6
|
+
Please do not use github issues to ask usage questions. We simply don't have
|
7
|
+
time to answer them all. Instead, please ask usage questions on Stack Overflow.
|
8
|
+
|
9
|
+
http://stackoverflow.com/tags/papertrail
|
10
|
+
|
11
|
+
Thanks, and happy versioning :)
|
data/README.md
CHANGED
@@ -1,72 +1,76 @@
|
|
1
|
-
# PaperTrail
|
1
|
+
# PaperTrail
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
[![Build Status][4]][5] [![Dependency Status][6]][7]
|
4
|
+
|
5
|
+
Track changes to your models, for auditing or versioning. See how a model looked
|
6
|
+
at any stage in its lifecycle, revert it to any version, or restore it after it
|
7
|
+
has been destroyed.
|
6
8
|
|
7
9
|
- [Features](#features)
|
8
10
|
- [Compatibility](#compatibility)
|
9
11
|
- [Installation](#installation)
|
10
12
|
- [API Summary](#api-summary)
|
11
13
|
- [Basic Usage](#basic-usage)
|
12
|
-
-
|
13
|
-
- [Choosing
|
14
|
-
- [Choosing
|
15
|
-
- [
|
16
|
-
- [
|
14
|
+
- Limiting What is Versioned, and When
|
15
|
+
- [Choosing Lifecycle Events To Monitor](#choosing-lifecycle-events-to-monitor)
|
16
|
+
- [Choosing When To Save New Versions](#choosing-when-to-save-new-versions)
|
17
|
+
- [Choosing Attributes To Monitor](#choosing-attributes-to-monitor)
|
18
|
+
- [Turning PaperTrail Off/On](#turning-papertrail-offon)
|
19
|
+
- [Limiting the Number of Versions Created](#limiting-the-number-of-versions-created)
|
20
|
+
- Working With Versions
|
21
|
+
- [Reverting And Undeleting A Model](#reverting-and-undeleting-a-model)
|
22
|
+
- [Navigating Versions](#navigating-versions)
|
23
|
+
- [Diffing Versions](#diffing-versions)
|
24
|
+
- [Deleting Old Versions](#deleting-old-versions)
|
17
25
|
- [Finding Out Who Was Responsible For A Change](#finding-out-who-was-responsible-for-a-change)
|
18
26
|
- [Custom Version Classes](#custom-version-classes)
|
19
27
|
- [Associations](#associations)
|
20
28
|
- [Storing metadata](#storing-metadata)
|
21
|
-
- [Diffing Versions](#diffing-versions)
|
22
|
-
- [Turning PaperTrail Off/On](#turning-papertrail-offon)
|
23
29
|
- [Using a custom serializer](#using-a-custom-serializer)
|
24
30
|
- [SerializedAttributes support](#serializedattributes-support)
|
25
|
-
- [Limiting the Number of Versions Created](#limiting-the-number-of-versions-created)
|
26
|
-
- [Deleting Old Versions](#deleting-old-versions)
|
27
31
|
- [Testing](#testing)
|
28
32
|
|
29
33
|
## Features
|
30
34
|
|
31
|
-
* Stores
|
32
|
-
* Does not store updates which don't change anything
|
33
|
-
*
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
37
|
-
*
|
38
|
-
*
|
39
|
-
*
|
40
|
-
*
|
41
|
-
*
|
42
|
-
*
|
43
|
-
*
|
44
|
-
*
|
45
|
-
*
|
46
|
-
*
|
47
|
-
*
|
48
|
-
*
|
49
|
-
*
|
50
|
-
*
|
51
|
-
|
35
|
+
* Stores create, update and destroy events
|
36
|
+
* Does not store updates which don't change anything
|
37
|
+
* Support for versioning associated records
|
38
|
+
* Can store metadata with each version record
|
39
|
+
* Who was responsible for a change
|
40
|
+
* Arbitrary model-level metadata (useful for filtering versions)
|
41
|
+
* Arbitrary controller-level information e.g. remote IP
|
42
|
+
* Configurable
|
43
|
+
* No configuration necessary, but if you want to ..
|
44
|
+
* Configure which events (create, update and destroy) are versioned
|
45
|
+
* Configure which attributes must change for an update to be versioned
|
46
|
+
* Turn off/on by model, request, or globally
|
47
|
+
* Use separate tables for separate models
|
48
|
+
* Extensible
|
49
|
+
* Write a custom version class for complete control
|
50
|
+
* Write custom version classes for each of your models
|
51
|
+
* Work with versions
|
52
|
+
* Restore any version, including the original, even once destroyed
|
53
|
+
* Restore any version even if the schema has since changed
|
54
|
+
* Restore the version as of a particular time
|
55
|
+
* Thoroughly tested
|
56
|
+
* Threadsafe
|
52
57
|
|
53
58
|
## Compatibility
|
54
59
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
The Rails 2.3 code is on the [`rails2`][11] branch and tagged `v1.x`. These branches are both stable with their respective versions of Rails but will not have new features added/backported to them.
|
60
|
+
| paper_trail | branch | tags | ruby | activerecord |
|
61
|
+
| ----------- | ---------- | ------ | -------- | ------------ |
|
62
|
+
| 4 | master | v4.x | >= 1.8.7 | >= 3.0, < 6 |
|
63
|
+
| 3 | 3.0-stable | v3.x | >= 1.8.7 | >= 3.0, < 5 |
|
64
|
+
| 2 | 2.7-stable | v2.x | >= 1.8.7 | >= 3.0, < 4 |
|
65
|
+
| 1 | rails2 | v1.x | >= 1.8.7 | >= 2.3, < 3 |
|
62
66
|
|
63
67
|
## Installation
|
64
68
|
|
65
|
-
### Rails 3
|
69
|
+
### Rails 3 and 4
|
66
70
|
|
67
71
|
1. Add PaperTrail to your `Gemfile`.
|
68
72
|
|
69
|
-
`gem 'paper_trail', '~> 4.0.
|
73
|
+
`gem 'paper_trail', '~> 4.0.1'`
|
70
74
|
|
71
75
|
2. Generate a migration which will add a `versions` table to your database.
|
72
76
|
|
@@ -89,7 +93,7 @@ setting up your app with PaperTrail will look something like this:
|
|
89
93
|
|
90
94
|
1. Add PaperTrail to your `Gemfile`.
|
91
95
|
|
92
|
-
`gem 'paper_trail', '~> 4.0.
|
96
|
+
`gem 'paper_trail', '~> 4.0.1'`
|
93
97
|
|
94
98
|
2. Generate a migration to add a `versions` table to your database.
|
95
99
|
|
@@ -435,6 +439,122 @@ class Article < ActiveRecord::Base
|
|
435
439
|
end
|
436
440
|
```
|
437
441
|
|
442
|
+
## Turning PaperTrail Off/On
|
443
|
+
|
444
|
+
Sometimes you don't want to store changes. Perhaps you are only interested in
|
445
|
+
changes made by your users and don't need to store changes you make yourself in,
|
446
|
+
say, a migration -- or when testing your application.
|
447
|
+
|
448
|
+
You can turn PaperTrail on or off in three ways: globally, per request, or per
|
449
|
+
class.
|
450
|
+
|
451
|
+
### Globally
|
452
|
+
|
453
|
+
On a global level you can turn PaperTrail off like this:
|
454
|
+
|
455
|
+
```ruby
|
456
|
+
PaperTrail.enabled = false
|
457
|
+
```
|
458
|
+
|
459
|
+
For example, you might want to disable PaperTrail in your Rails application's
|
460
|
+
test environment to speed up your tests. This will do it (note: this gets done
|
461
|
+
automatically for `RSpec` and `Cucumber`, please see the [Testing
|
462
|
+
section](#testing)):
|
463
|
+
|
464
|
+
```ruby
|
465
|
+
# in config/environments/test.rb
|
466
|
+
config.after_initialize do
|
467
|
+
PaperTrail.enabled = false
|
468
|
+
end
|
469
|
+
```
|
470
|
+
|
471
|
+
If you disable PaperTrail in your test environment but want to enable it for
|
472
|
+
specific tests, you can add a helper like this to your test helper:
|
473
|
+
|
474
|
+
```ruby
|
475
|
+
# in test/test_helper.rb
|
476
|
+
def with_versioning
|
477
|
+
was_enabled = PaperTrail.enabled?
|
478
|
+
was_enabled_for_controller = PaperTrail.enabled_for_controller?
|
479
|
+
PaperTrail.enabled = true
|
480
|
+
PaperTrail.enabled_for_controller = true
|
481
|
+
begin
|
482
|
+
yield
|
483
|
+
ensure
|
484
|
+
PaperTrail.enabled = was_enabled
|
485
|
+
PaperTrail.enabled_for_controller = was_enabled_for_controller
|
486
|
+
end
|
487
|
+
end
|
488
|
+
```
|
489
|
+
|
490
|
+
And then use it in your tests like this:
|
491
|
+
|
492
|
+
```ruby
|
493
|
+
test "something that needs versioning" do
|
494
|
+
with_versioning do
|
495
|
+
# your test
|
496
|
+
end
|
497
|
+
end
|
498
|
+
```
|
499
|
+
|
500
|
+
### Per request
|
501
|
+
|
502
|
+
You can turn PaperTrail on or off per request by adding a
|
503
|
+
`paper_trail_enabled_for_controller` method to your controller which returns
|
504
|
+
`true` or `false`:
|
505
|
+
|
506
|
+
```ruby
|
507
|
+
class ApplicationController < ActionController::Base
|
508
|
+
def paper_trail_enabled_for_controller
|
509
|
+
request.user_agent != 'Disable User-Agent'
|
510
|
+
end
|
511
|
+
end
|
512
|
+
```
|
513
|
+
|
514
|
+
### Per class
|
515
|
+
|
516
|
+
If you are about to change some widgets and you don't want a paper trail of your
|
517
|
+
changes, you can turn PaperTrail off like this:
|
518
|
+
|
519
|
+
```ruby
|
520
|
+
Widget.paper_trail_off!
|
521
|
+
```
|
522
|
+
|
523
|
+
And on again like this:
|
524
|
+
|
525
|
+
```ruby
|
526
|
+
Widget.paper_trail_on!
|
527
|
+
```
|
528
|
+
|
529
|
+
### Per method call
|
530
|
+
|
531
|
+
You can call a method without creating a new version using `without_versioning`.
|
532
|
+
It takes either a method name as a symbol:
|
533
|
+
|
534
|
+
```ruby
|
535
|
+
@widget.without_versioning :destroy
|
536
|
+
```
|
537
|
+
|
538
|
+
Or a block:
|
539
|
+
|
540
|
+
```ruby
|
541
|
+
@widget.without_versioning do
|
542
|
+
@widget.update_attributes :name => 'Ford'
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
## Limiting the Number of Versions Created
|
547
|
+
|
548
|
+
Configure `version_limit` to cap the number of versions saved per record. This
|
549
|
+
does not apply to `create` events.
|
550
|
+
|
551
|
+
```ruby
|
552
|
+
# Limit: 4 versions per record (3 most recent, plus a `create` event)
|
553
|
+
PaperTrail.config.version_limit = 3
|
554
|
+
# Remove the limit
|
555
|
+
PaperTrail.config.version_limit = nil
|
556
|
+
```
|
557
|
+
|
438
558
|
## Reverting And Undeleting A Model
|
439
559
|
|
440
560
|
PaperTrail makes reverting to a previous version easy:
|
@@ -528,6 +648,85 @@ And you can perform `WHERE` queries for object versions based on attributes:
|
|
528
648
|
PaperTrail::Version.where_object(content: "Hello", title: "Article")
|
529
649
|
```
|
530
650
|
|
651
|
+
## Diffing Versions
|
652
|
+
|
653
|
+
There are two scenarios: diffing adjacent versions and diffing non-adjacent
|
654
|
+
versions.
|
655
|
+
|
656
|
+
The best way to diff adjacent versions is to get PaperTrail to do it for you.
|
657
|
+
If you add an `object_changes` text column to your `versions` table, either at
|
658
|
+
installation time with the `rails generate paper_trail:install --with-changes`
|
659
|
+
option or manually, PaperTrail will store the `changes` diff (excluding any
|
660
|
+
attributes PaperTrail is ignoring) in each `update` version. You can use the
|
661
|
+
`version.changeset` method to retrieve it. For example:
|
662
|
+
|
663
|
+
```ruby
|
664
|
+
widget = Widget.create :name => 'Bob'
|
665
|
+
widget.versions.last.changeset
|
666
|
+
# {
|
667
|
+
# "name"=>[nil, "Bob"],
|
668
|
+
# "created_at"=>[nil, 2015-08-10 04:10:40 UTC],
|
669
|
+
# "updated_at"=>[nil, 2015-08-10 04:10:40 UTC],
|
670
|
+
# "id"=>[nil, 1]
|
671
|
+
# }
|
672
|
+
widget.update_attributes :name => 'Robert'
|
673
|
+
widget.versions.last.changeset
|
674
|
+
# {
|
675
|
+
# "name"=>["Bob", "Robert"],
|
676
|
+
# "updated_at"=>[2015-08-10 04:13:19 UTC, 2015-08-10 04:13:19 UTC]
|
677
|
+
# }
|
678
|
+
widget.destroy
|
679
|
+
widget.versions.last.changeset
|
680
|
+
# {}
|
681
|
+
```
|
682
|
+
|
683
|
+
The `object_changes` are only stored for creation and updates, not when an
|
684
|
+
object is destroyed.
|
685
|
+
|
686
|
+
Please be aware that PaperTrail doesn't use diffs internally. When I designed
|
687
|
+
PaperTrail I wanted simplicity and robustness so I decided to make each version
|
688
|
+
of an object self-contained. A version stores all of its object's data, not a
|
689
|
+
diff from the previous version. This means you can delete any version without
|
690
|
+
affecting any other.
|
691
|
+
|
692
|
+
To diff non-adjacent versions you'll have to write your own code. These
|
693
|
+
libraries may help:
|
694
|
+
|
695
|
+
For diffing two strings:
|
696
|
+
|
697
|
+
* [htmldiff][19]: expects but doesn't require HTML input and produces HTML
|
698
|
+
output. Works very well but slows down significantly on large (e.g. 5,000
|
699
|
+
word) inputs.
|
700
|
+
* [differ][20]: expects plain text input and produces plain
|
701
|
+
text/coloured/HTML/any output. Can do character-wise, word-wise, line-wise,
|
702
|
+
or arbitrary-boundary-string-wise diffs. Works very well on non-HTML input.
|
703
|
+
* [diff-lcs][21]: old-school, line-wise diffs.
|
704
|
+
|
705
|
+
For diffing two ActiveRecord objects:
|
706
|
+
|
707
|
+
* [Jeremy Weiskotten's PaperTrail fork][22]: uses ActiveSupport's diff to return
|
708
|
+
an array of hashes of the changes.
|
709
|
+
* [activerecord-diff][23]: rather like ActiveRecord::Dirty but also allows you
|
710
|
+
to specify which columns to compare.
|
711
|
+
|
712
|
+
If you wish to selectively record changes for some models but not others you
|
713
|
+
can opt out of recording changes by passing `:save_changes => false` to your
|
714
|
+
`has_paper_trail` method declaration.
|
715
|
+
|
716
|
+
## Deleting Old Versions
|
717
|
+
|
718
|
+
Over time your `versions` table will grow to an unwieldy size. Because each
|
719
|
+
version is self-contained (see the Diffing section above for more) you can
|
720
|
+
simply delete any records you don't want any more. For example:
|
721
|
+
|
722
|
+
```sql
|
723
|
+
sql> delete from versions where created_at < 2010-06-01;
|
724
|
+
```
|
725
|
+
|
726
|
+
```ruby
|
727
|
+
PaperTrail::Version.delete_all ["created_at < ?", 1.week.ago]
|
728
|
+
```
|
729
|
+
|
531
730
|
## Finding Out Who Was Responsible For A Change
|
532
731
|
|
533
732
|
If your `ApplicationController` has a `current_user` method, PaperTrail will
|
@@ -670,6 +869,11 @@ end
|
|
670
869
|
|
671
870
|
## Associations
|
672
871
|
|
872
|
+
**Experimental Feature: Known Issues:**
|
873
|
+
[#542](https://github.com/airblade/paper_trail/issues/542),
|
874
|
+
[#590](https://github.com/airblade/paper_trail/issues/590).
|
875
|
+
See also: Caveats below.
|
876
|
+
|
673
877
|
PaperTrail can restore three types of associations: Has-One, Has-Many, and
|
674
878
|
Has-Many-Through. In order to do this, you will need to create a
|
675
879
|
`version_associations` table, either at installation time with the `rails
|
@@ -884,7 +1088,7 @@ end
|
|
884
1088
|
|
885
1089
|
### Protected Attributes and Metadata
|
886
1090
|
|
887
|
-
If you are using rails 3 or the [protected_attributes][17] gem you must declare
|
1091
|
+
If you are using rails 3 or the [protected_attributes][17] gem you must declare
|
888
1092
|
your metadata columns to be `attr_accessible`.
|
889
1093
|
|
890
1094
|
```ruby
|
@@ -900,164 +1104,6 @@ end
|
|
900
1104
|
If you're using [strong_parameters][18] instead of [protected_attributes][17]
|
901
1105
|
then there is no need to use `attr_accessible`.
|
902
1106
|
|
903
|
-
## Diffing Versions
|
904
|
-
|
905
|
-
There are two scenarios: diffing adjacent versions and diffing non-adjacent
|
906
|
-
versions.
|
907
|
-
|
908
|
-
The best way to diff adjacent versions is to get PaperTrail to do it for you.
|
909
|
-
If you add an `object_changes` text column to your `versions` table, either at
|
910
|
-
installation time with the `rails generate paper_trail:install --with-changes`
|
911
|
-
option or manually, PaperTrail will store the `changes` diff (excluding any
|
912
|
-
attributes PaperTrail is ignoring) in each `update` version. You can use the
|
913
|
-
`version.changeset` method to retrieve it. For example:
|
914
|
-
|
915
|
-
```ruby
|
916
|
-
widget = Widget.create :name => 'Bob'
|
917
|
-
widget.versions.last.changeset # {'name' => [nil, 'Bob']}
|
918
|
-
widget.update_attributes :name => 'Robert'
|
919
|
-
widget.versions.last.changeset # {'name' => ['Bob', 'Robert']}
|
920
|
-
widget.destroy
|
921
|
-
widget.versions.last.changeset # {}
|
922
|
-
```
|
923
|
-
|
924
|
-
Note PaperTrail only stores the changes for creation and updates; it doesn't
|
925
|
-
store anything when an object is destroyed.
|
926
|
-
|
927
|
-
Please be aware that PaperTrail doesn't use diffs internally. When I designed
|
928
|
-
PaperTrail I wanted simplicity and robustness so I decided to make each version
|
929
|
-
of an object self-contained. A version stores all of its object's data, not a
|
930
|
-
diff from the previous version. This means you can delete any version without
|
931
|
-
affecting any other.
|
932
|
-
|
933
|
-
To diff non-adjacent versions you'll have to write your own code. These
|
934
|
-
libraries may help:
|
935
|
-
|
936
|
-
For diffing two strings:
|
937
|
-
|
938
|
-
* [htmldiff][19]: expects but doesn't require HTML input and produces HTML
|
939
|
-
output. Works very well but slows down significantly on large (e.g. 5,000
|
940
|
-
word) inputs.
|
941
|
-
* [differ][20]: expects plain text input and produces plain
|
942
|
-
text/coloured/HTML/any output. Can do character-wise, word-wise, line-wise,
|
943
|
-
or arbitrary-boundary-string-wise diffs. Works very well on non-HTML input.
|
944
|
-
* [diff-lcs][21]: old-school, line-wise diffs.
|
945
|
-
|
946
|
-
For diffing two ActiveRecord objects:
|
947
|
-
|
948
|
-
* [Jeremy Weiskotten's PaperTrail fork][22]: uses ActiveSupport's diff to return
|
949
|
-
an array of hashes of the changes.
|
950
|
-
* [activerecord-diff][23]: rather like ActiveRecord::Dirty but also allows you
|
951
|
-
to specify which columns to compare.
|
952
|
-
|
953
|
-
If you wish to selectively record changes for some models but not others you
|
954
|
-
can opt out of recording changes by passing `:save_changes => false` to your
|
955
|
-
`has_paper_trail` method declaration.
|
956
|
-
|
957
|
-
## Turning PaperTrail Off/On
|
958
|
-
|
959
|
-
Sometimes you don't want to store changes. Perhaps you are only interested in
|
960
|
-
changes made by your users and don't need to store changes you make yourself in,
|
961
|
-
say, a migration -- or when testing your application.
|
962
|
-
|
963
|
-
You can turn PaperTrail on or off in three ways: globally, per request, or per
|
964
|
-
class.
|
965
|
-
|
966
|
-
### Globally
|
967
|
-
|
968
|
-
On a global level you can turn PaperTrail off like this:
|
969
|
-
|
970
|
-
```ruby
|
971
|
-
PaperTrail.enabled = false
|
972
|
-
```
|
973
|
-
|
974
|
-
For example, you might want to disable PaperTrail in your Rails application's
|
975
|
-
test environment to speed up your tests. This will do it (note: this gets done
|
976
|
-
automatically for `RSpec` and `Cucumber`, please see the [Testing
|
977
|
-
section](#testing)):
|
978
|
-
|
979
|
-
```ruby
|
980
|
-
# in config/environments/test.rb
|
981
|
-
config.after_initialize do
|
982
|
-
PaperTrail.enabled = false
|
983
|
-
end
|
984
|
-
```
|
985
|
-
|
986
|
-
If you disable PaperTrail in your test environment but want to enable it for
|
987
|
-
specific tests, you can add a helper like this to your test helper:
|
988
|
-
|
989
|
-
```ruby
|
990
|
-
# in test/test_helper.rb
|
991
|
-
def with_versioning
|
992
|
-
was_enabled = PaperTrail.enabled?
|
993
|
-
was_enabled_for_controller = PaperTrail.enabled_for_controller?
|
994
|
-
PaperTrail.enabled = true
|
995
|
-
PaperTrail.enabled_for_controller = true
|
996
|
-
begin
|
997
|
-
yield
|
998
|
-
ensure
|
999
|
-
PaperTrail.enabled = was_enabled
|
1000
|
-
PaperTrail.enabled_for_controller = was_enabled_for_controller
|
1001
|
-
end
|
1002
|
-
end
|
1003
|
-
```
|
1004
|
-
|
1005
|
-
And then use it in your tests like this:
|
1006
|
-
|
1007
|
-
```ruby
|
1008
|
-
test "something that needs versioning" do
|
1009
|
-
with_versioning do
|
1010
|
-
# your test
|
1011
|
-
end
|
1012
|
-
end
|
1013
|
-
```
|
1014
|
-
|
1015
|
-
### Per request
|
1016
|
-
|
1017
|
-
You can turn PaperTrail on or off per request by adding a
|
1018
|
-
`paper_trail_enabled_for_controller` method to your controller which returns
|
1019
|
-
`true` or `false`:
|
1020
|
-
|
1021
|
-
```ruby
|
1022
|
-
class ApplicationController < ActionController::Base
|
1023
|
-
def paper_trail_enabled_for_controller
|
1024
|
-
request.user_agent != 'Disable User-Agent'
|
1025
|
-
end
|
1026
|
-
end
|
1027
|
-
```
|
1028
|
-
|
1029
|
-
### Per class
|
1030
|
-
|
1031
|
-
If you are about to change some widgets and you don't want a paper trail of your
|
1032
|
-
changes, you can turn PaperTrail off like this:
|
1033
|
-
|
1034
|
-
```ruby
|
1035
|
-
Widget.paper_trail_off!
|
1036
|
-
```
|
1037
|
-
|
1038
|
-
And on again like this:
|
1039
|
-
|
1040
|
-
```ruby
|
1041
|
-
Widget.paper_trail_on!
|
1042
|
-
```
|
1043
|
-
|
1044
|
-
### Per method call
|
1045
|
-
|
1046
|
-
You can call a method without creating a new version using `without_versioning`.
|
1047
|
-
It takes either a method name as a symbol:
|
1048
|
-
|
1049
|
-
```ruby
|
1050
|
-
@widget.without_versioning :destroy
|
1051
|
-
```
|
1052
|
-
|
1053
|
-
Or a block:
|
1054
|
-
|
1055
|
-
```ruby
|
1056
|
-
@widget.without_versioning do
|
1057
|
-
@widget.update_attributes :name => 'Ford'
|
1058
|
-
end
|
1059
|
-
```
|
1060
|
-
|
1061
1107
|
## Using a custom serializer
|
1062
1108
|
|
1063
1109
|
By default, PaperTrail stores your changes as a `YAML` dump. You can override
|
@@ -1091,6 +1137,17 @@ end
|
|
1091
1137
|
Note: You don't need to use a particular serializer for the PostgreSQL `JSON`
|
1092
1138
|
column type.
|
1093
1139
|
|
1140
|
+
#### Convert a column from text to json
|
1141
|
+
|
1142
|
+
Postgres' `alter column` command will not automatically convert a `text`
|
1143
|
+
column to `json`, but it can still be done with plain SQL.
|
1144
|
+
|
1145
|
+
```sql
|
1146
|
+
alter table versions
|
1147
|
+
alter column object type json
|
1148
|
+
using object::json;
|
1149
|
+
```
|
1150
|
+
|
1094
1151
|
## SerializedAttributes support
|
1095
1152
|
|
1096
1153
|
PaperTrail has a config option that can be used to enable/disable whether
|
@@ -1110,32 +1167,6 @@ PaperTrail.config.serialized_attributes = false
|
|
1110
1167
|
PaperTrail.serialized_attributes?
|
1111
1168
|
```
|
1112
1169
|
|
1113
|
-
## Limiting the Number of Versions Created
|
1114
|
-
|
1115
|
-
Configure `version_limit` to cap the number of versions saved per record. This
|
1116
|
-
does not apply to `create` events.
|
1117
|
-
|
1118
|
-
```ruby
|
1119
|
-
# Limit: 4 versions per record (3 most recent, plus a `create` event)
|
1120
|
-
PaperTrail.config.version_limit = 3
|
1121
|
-
# Remove the limit
|
1122
|
-
PaperTrail.config.version_limit = nil
|
1123
|
-
```
|
1124
|
-
|
1125
|
-
## Deleting Old Versions
|
1126
|
-
|
1127
|
-
Over time your `versions` table will grow to an unwieldy size. Because each
|
1128
|
-
version is self-contained (see the Diffing section above for more) you can
|
1129
|
-
simply delete any records you don't want any more. For example:
|
1130
|
-
|
1131
|
-
```sql
|
1132
|
-
sql> delete from versions where created_at < 2010-06-01;
|
1133
|
-
```
|
1134
|
-
|
1135
|
-
```ruby
|
1136
|
-
PaperTrail::Version.delete_all ["created_at < ?", 1.week.ago]
|
1137
|
-
```
|
1138
|
-
|
1139
1170
|
## Testing
|
1140
1171
|
|
1141
1172
|
You may want to turn PaperTrail off to speed up your tests. See the [Turning
|