paper_trail 3.0.0.beta1 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -3
- data/CHANGELOG.md +15 -0
- data/README.md +113 -24
- data/Rakefile +2 -5
- data/lib/generators/paper_trail/install_generator.rb +1 -1
- data/lib/paper_trail.rb +16 -3
- data/lib/paper_trail/config.rb +1 -1
- data/lib/paper_trail/frameworks/cucumber.rb +22 -24
- data/lib/paper_trail/frameworks/rails.rb +1 -1
- data/lib/paper_trail/frameworks/rspec.rb +16 -18
- data/lib/paper_trail/frameworks/sinatra.rb +4 -4
- data/lib/paper_trail/has_paper_trail.rb +68 -39
- data/lib/paper_trail/serializers/json.rb +1 -1
- data/lib/paper_trail/serializers/yaml.rb +3 -3
- data/lib/paper_trail/version.rb +73 -78
- data/lib/paper_trail/version_number.rb +1 -1
- data/paper_trail.gemspec +4 -2
- data/spec/models/version_spec.rb +44 -0
- data/spec/models/widget_spec.rb +16 -6
- data/spec/modules/version_concern_spec.rb +50 -0
- data/spec/paper_trail_spec.rb +18 -20
- data/spec/spec_helper.rb +3 -1
- data/test/custom_json_serializer.rb +1 -1
- data/test/dummy/app/controllers/articles_controller.rb +10 -0
- data/test/dummy/app/models/article.rb +2 -2
- data/test/dummy/app/models/wotsit.rb +4 -0
- data/test/dummy/config/environments/development.rb +1 -1
- data/test/dummy/config/routes.rb +1 -0
- data/test/functional/enabled_for_controller_test.rb +29 -0
- data/test/functional/modular_sinatra_test.rb +1 -1
- data/test/functional/sinatra_test.rb +1 -1
- data/test/test_helper.rb +2 -7
- data/test/unit/model_test.rb +56 -2
- data/test/unit/serializer_test.rb +6 -6
- data/test/unit/serializers/json_test.rb +7 -7
- data/test/unit/serializers/mixin_yaml_test.rb +1 -1
- data/test/unit/serializers/yaml_test.rb +8 -8
- data/test/unit/version_test.rb +41 -12
- metadata +45 -16
data/paper_trail.gemspec
CHANGED
@@ -4,11 +4,13 @@ require 'paper_trail/version_number'
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'paper_trail'
|
6
6
|
s.version = PaperTrail::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
7
8
|
s.summary = "Track changes to your models' data. Good for auditing or versioning."
|
8
9
|
s.description = s.summary
|
9
10
|
s.homepage = 'http://github.com/airblade/paper_trail'
|
10
11
|
s.authors = ['Andy Stewart', 'Ben Atkins']
|
11
12
|
s.email = 'boss@airbladesoftware.com'
|
13
|
+
s.license = 'MIT'
|
12
14
|
|
13
15
|
s.files = `git ls-files`.split("\n")
|
14
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -16,10 +18,10 @@ Gem::Specification.new do |s|
|
|
16
18
|
s.require_paths = ['lib']
|
17
19
|
|
18
20
|
s.add_dependency 'activerecord', ['>= 3.0', '< 5.0']
|
21
|
+
s.add_dependency 'activesupport', ['>= 3.0', '< 5.0']
|
19
22
|
|
20
23
|
s.add_development_dependency 'rake'
|
21
24
|
s.add_development_dependency 'shoulda', '~> 3.5'
|
22
|
-
# s.add_development_dependency 'shoulda-matchers', '~> 1.5'
|
23
25
|
s.add_development_dependency 'ffaker', '>= 1.15'
|
24
26
|
s.add_development_dependency 'railties', ['>= 3.0', '< 5.0']
|
25
27
|
s.add_development_dependency 'sinatra', '~> 1.0'
|
@@ -30,6 +32,6 @@ Gem::Specification.new do |s|
|
|
30
32
|
unless defined?(JRUBY_VERSION)
|
31
33
|
s.add_development_dependency 'sqlite3', '~> 1.2'
|
32
34
|
else
|
33
|
-
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter',
|
35
|
+
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.3'
|
34
36
|
end
|
35
37
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PaperTrail::Version do
|
4
|
+
it "should include the `VersionConcern` module to get base functionality" do
|
5
|
+
PaperTrail::Version.should include(PaperTrail::VersionConcern)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Attributes" do
|
9
|
+
it { should have_db_column(:item_type).of_type(:string) }
|
10
|
+
it { should have_db_column(:item_id).of_type(:integer) }
|
11
|
+
it { should have_db_column(:event).of_type(:string) }
|
12
|
+
it { should have_db_column(:whodunnit).of_type(:string) }
|
13
|
+
it { should have_db_column(:object).of_type(:text) }
|
14
|
+
it { should have_db_column(:created_at).of_type(:datetime) }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "Indexes" do
|
18
|
+
it { should have_db_index([:item_type, :item_id]) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Methods" do
|
22
|
+
describe "Instance" do
|
23
|
+
subject { PaperTrail::Version.new(attributes) rescue PaperTrail::Version.new }
|
24
|
+
|
25
|
+
describe :terminator do
|
26
|
+
it { should respond_to(:terminator) }
|
27
|
+
|
28
|
+
let(:attributes) { {:whodunnit => Faker::Name.first_name} }
|
29
|
+
|
30
|
+
it "is an alias for the `whodunnit` attribute" do
|
31
|
+
subject.whodunnit.should == attributes[:whodunnit]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe :version_author do
|
36
|
+
it { should respond_to(:terminator) }
|
37
|
+
|
38
|
+
it "should be an alias for the `terminator` method" do
|
39
|
+
subject.method(:version_author).should == subject.method(:terminator)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/models/widget_spec.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Widget do
|
4
|
-
|
4
|
+
describe '`be_versioned` matcher' do
|
5
|
+
it { should be_versioned }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "`versioning` option" do
|
9
|
+
let(:widget) { Widget.create :name => 'Bob', :an_integer => 1 }
|
10
|
+
|
11
|
+
context :enabled, :versioning => true do
|
12
|
+
it 'should enable versioning for models wrapped within a block' do
|
13
|
+
widget.versions.size.should == 1
|
14
|
+
end
|
15
|
+
end
|
5
16
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
widget.versions.size.should == 1
|
17
|
+
context '`disabled` (default)' do
|
18
|
+
it 'should not enable versioning for models wrapped within a block not marked to used versioning' do
|
19
|
+
widget.versions.size.should == 0
|
20
|
+
end
|
11
21
|
end
|
12
22
|
end
|
13
23
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PaperTrail::VersionConcern do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
module Foo
|
7
|
+
class Base < ActiveRecord::Base
|
8
|
+
self.abstract_class = true
|
9
|
+
end
|
10
|
+
|
11
|
+
class Document < Base
|
12
|
+
has_paper_trail :class_name => 'Foo::Version'
|
13
|
+
end
|
14
|
+
|
15
|
+
class Version < Base
|
16
|
+
include PaperTrail::VersionConcern
|
17
|
+
end
|
18
|
+
end
|
19
|
+
Foo::Base.establish_connection(:adapter => 'sqlite3', :database => File.expand_path('../../../test/dummy/db/test-foo.sqlite3', __FILE__))
|
20
|
+
|
21
|
+
module Bar
|
22
|
+
class Base < ActiveRecord::Base
|
23
|
+
self.abstract_class = true
|
24
|
+
end
|
25
|
+
|
26
|
+
class Document < Base
|
27
|
+
has_paper_trail :class_name => 'Bar::Version'
|
28
|
+
end
|
29
|
+
|
30
|
+
class Version < Base
|
31
|
+
include PaperTrail::VersionConcern
|
32
|
+
end
|
33
|
+
end
|
34
|
+
Bar::Base.establish_connection(:adapter => 'sqlite3', :database => File.expand_path('../../../test/dummy/db/test-bar.sqlite3', __FILE__))
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'allows included class to have different connections' do
|
38
|
+
Foo::Version.connection.should_not eq Bar::Version.connection
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'allows custom version class to share connection with superclass' do
|
42
|
+
Foo::Version.connection.should eq Foo::Document.connection
|
43
|
+
Bar::Version.connection.should eq Bar::Document.connection
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'can be used with class_name option' do
|
47
|
+
Foo::Document.version_class_name.should eq 'Foo::Version'
|
48
|
+
Bar::Document.version_class_name.should eq 'Bar::Version'
|
49
|
+
end
|
50
|
+
end
|
data/spec/paper_trail_spec.rb
CHANGED
@@ -1,31 +1,29 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "PaperTrail RSpec Helper" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
::PaperTrail.should_not be_enabled
|
8
|
-
end
|
9
|
-
it 'should turn versioning on in a with_versioning block' do
|
10
|
-
::PaperTrail.should_not be_enabled
|
11
|
-
with_versioning do
|
12
|
-
::PaperTrail.should be_enabled
|
13
|
-
end
|
14
|
-
::PaperTrail.should_not be_enabled
|
15
|
-
end
|
4
|
+
context 'default' do
|
5
|
+
it 'should have versioning off by default' do
|
6
|
+
::PaperTrail.should_not be_enabled
|
16
7
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
it 'should turn versioning on in a with_versioning block' do
|
9
|
+
::PaperTrail.should_not be_enabled
|
10
|
+
with_versioning do
|
20
11
|
::PaperTrail.should be_enabled
|
21
12
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
13
|
+
::PaperTrail.should_not be_enabled
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context '`versioning: true`', :versioning => true do
|
18
|
+
it 'should have versioning on by default' do
|
19
|
+
::PaperTrail.should be_enabled
|
20
|
+
end
|
21
|
+
it 'should keep versioning on after a with_versioning block' do
|
22
|
+
::PaperTrail.should be_enabled
|
23
|
+
with_versioning do
|
27
24
|
::PaperTrail.should be_enabled
|
28
25
|
end
|
26
|
+
::PaperTrail.should be_enabled
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
ENV["RAILS_ENV"] ||= 'test'
|
2
|
-
require File.expand_path('../../test/dummy/config/environment', __FILE__)
|
3
2
|
|
3
|
+
require File.expand_path('../../test/dummy/config/environment', __FILE__)
|
4
4
|
require 'rspec/rails'
|
5
5
|
require 'rspec/autorun'
|
6
|
+
require 'shoulda/matchers'
|
7
|
+
require 'ffaker'
|
6
8
|
|
7
9
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
8
10
|
# in spec/support/ and its subdirectories.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Article < ActiveRecord::Base
|
2
|
-
has_paper_trail :ignore => :title,
|
3
|
-
:only => [:content],
|
2
|
+
has_paper_trail :ignore => [:title, { :abstract => Proc.new { |obj| ['ignore abstract', 'Other abstract'].include? obj.abstract } } ],
|
3
|
+
:only => [:content, { :abstract => Proc.new { |obj| obj.abstract.present? } } ],
|
4
4
|
:skip => [:file_upload],
|
5
5
|
:meta => {
|
6
6
|
:answer => 42,
|
@@ -27,7 +27,7 @@ Dummy::Application.configure do
|
|
27
27
|
|
28
28
|
# Log the query plan for queries taking more than this (works
|
29
29
|
# with SQLite, MySQL, and PostgreSQL)
|
30
|
-
config.active_record.auto_explain_threshold_in_seconds = 0.5
|
30
|
+
# config.active_record.auto_explain_threshold_in_seconds = 0.5
|
31
31
|
|
32
32
|
# Do not compress assets
|
33
33
|
config.assets.compress = false
|
data/test/dummy/config/routes.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EnabledForControllerTest < ActionController::TestCase
|
4
|
+
tests ArticlesController
|
5
|
+
|
6
|
+
context "`PaperTrail.enabled? == true`" do
|
7
|
+
should 'enabled_for_controller?.should == true' do
|
8
|
+
assert PaperTrail.enabled?
|
9
|
+
post :create, :article => { :title => 'Doh', :content => Faker::Lorem.sentence }
|
10
|
+
assert_not_nil assigns(:article)
|
11
|
+
assert PaperTrail.enabled_for_controller?
|
12
|
+
assert_equal 1, assigns(:article).versions.length
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "`PaperTrail.enabled? == false`" do
|
17
|
+
setup { PaperTrail.enabled = false }
|
18
|
+
|
19
|
+
should 'enabled_for_controller?.should == false' do
|
20
|
+
assert !PaperTrail.enabled?
|
21
|
+
post :create, :article => { :title => 'Doh', :content => Faker::Lorem.sentence }
|
22
|
+
assert !PaperTrail.enabled_for_controller?
|
23
|
+
assert_equal 0, assigns(:article).versions.length
|
24
|
+
end
|
25
|
+
|
26
|
+
teardown { PaperTrail.enabled = true }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -4,7 +4,7 @@ require 'sinatra/base'
|
|
4
4
|
# --- Tests for modular `Sinatra::Base` style ----
|
5
5
|
class BaseApp < Sinatra::Base
|
6
6
|
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => File.expand_path('../../dummy/db/test.sqlite3', __FILE__))
|
7
|
-
register Sinatra
|
7
|
+
register PaperTrail::Sinatra
|
8
8
|
|
9
9
|
get '/test' do
|
10
10
|
Widget.create!(:name => 'foo')
|
@@ -4,7 +4,7 @@ require 'test_helper'
|
|
4
4
|
# --- Tests for non-modular `Sinatra::Application` style ----
|
5
5
|
class Sinatra::Application
|
6
6
|
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => File.expand_path('../../dummy/db/test.sqlite3', __FILE__))
|
7
|
-
register Sinatra
|
7
|
+
register PaperTrail::Sinatra # we shouldn't actually need this line if I'm not mistaken but the tests seem to fail without it ATM
|
8
8
|
|
9
9
|
get '/test' do
|
10
10
|
Widget.create!(:name => 'bar')
|
data/test/test_helper.rb
CHANGED
@@ -3,16 +3,11 @@ ENV["RAILS_ENV"] = "test"
|
|
3
3
|
|
4
4
|
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
5
5
|
require "rails/test_help"
|
6
|
-
|
7
|
-
#ActionMailer::Base.delivery_method = :test
|
8
|
-
#ActionMailer::Base.perform_deliveries = true
|
9
|
-
#ActionMailer::Base.default_url_options[:host] = "test.com"
|
10
|
-
|
11
|
-
Rails.backtrace_cleaner.remove_silencers!
|
12
|
-
|
13
6
|
require 'shoulda'
|
14
7
|
require 'ffaker'
|
15
8
|
|
9
|
+
Rails.backtrace_cleaner.remove_silencers!
|
10
|
+
|
16
11
|
# Run any available migration
|
17
12
|
ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
|
18
13
|
|
data/test/unit/model_test.rb
CHANGED
@@ -11,8 +11,21 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
11
11
|
should 'not change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
12
12
|
end
|
13
13
|
|
14
|
-
context 'which updates an ignored column
|
15
|
-
setup { @article.update_attributes :
|
14
|
+
context 'which updates an ignored column with truly Proc' do
|
15
|
+
setup { @article.update_attributes :abstract => 'ignore abstract' }
|
16
|
+
should 'not change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'which updates an ignored column with falsy Proc' do
|
20
|
+
setup { @article.update_attributes :abstract => 'do not ignore abstract!' }
|
21
|
+
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'which updates an ignored column, ignored with truly Proc and a selected column' do
|
25
|
+
setup { @article.update_attributes :title => 'My first title',
|
26
|
+
:content => 'Some text here.',
|
27
|
+
:abstract => 'ignore abstract'
|
28
|
+
}
|
16
29
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
17
30
|
|
18
31
|
should "show the new version in the model's `versions` association" do
|
@@ -24,6 +37,22 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
24
37
|
end
|
25
38
|
end
|
26
39
|
|
40
|
+
context 'which updates an ignored column, ignored with falsy Proc and a selected column' do
|
41
|
+
setup { @article.update_attributes :title => 'My first title',
|
42
|
+
:content => 'Some text here.',
|
43
|
+
:abstract => 'do not ignore abstract'
|
44
|
+
}
|
45
|
+
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
46
|
+
|
47
|
+
should "show the new version in the model's `versions` association" do
|
48
|
+
assert_equal(2, @article.versions.size)
|
49
|
+
end
|
50
|
+
|
51
|
+
should 'have stored only non-ignored attributes' do
|
52
|
+
assert_equal ({'content' => [nil, 'Some text here.'], 'abstract' => [nil, 'do not ignore abstract']}), @article.versions.last.changeset
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
27
56
|
context 'which updates a selected column' do
|
28
57
|
setup { @article.update_attributes :content => 'Some text here.' }
|
29
58
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
@@ -553,6 +582,31 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|
553
582
|
end
|
554
583
|
|
555
584
|
|
585
|
+
context 'Timestamps' do
|
586
|
+
setup do
|
587
|
+
@wotsit = Wotsit.create! :name => 'wotsit'
|
588
|
+
end
|
589
|
+
|
590
|
+
should 'record timestamps' do
|
591
|
+
@wotsit.update_attributes! :name => 'changed'
|
592
|
+
assert_not_nil @wotsit.versions.last.reify.created_at
|
593
|
+
assert_not_nil @wotsit.versions.last.reify.updated_at
|
594
|
+
end
|
595
|
+
|
596
|
+
should 'not generate warning' do
|
597
|
+
# Tests that it doesn't try to write created_on as an attribute just because a created_on
|
598
|
+
# method exists.
|
599
|
+
warnings = capture(:stderr) { # Deprecation warning in Rails 3.2
|
600
|
+
assert_nothing_raised { # ActiveModel::MissingAttributeError in Rails 4
|
601
|
+
@wotsit.update_attributes! :name => 'changed'
|
602
|
+
}
|
603
|
+
}
|
604
|
+
assert_equal '', warnings
|
605
|
+
end
|
606
|
+
|
607
|
+
end
|
608
|
+
|
609
|
+
|
556
610
|
context 'A subclass' do
|
557
611
|
setup do
|
558
612
|
@foo = FooWidget.create
|
@@ -14,16 +14,16 @@ class SerializerTest < ActiveSupport::TestCase
|
|
14
14
|
@fluxor.update_attributes :name => 'Some more text.'
|
15
15
|
end
|
16
16
|
|
17
|
-
should 'work with the default
|
17
|
+
should 'work with the default `YAML` serializer' do
|
18
18
|
# Normal behaviour
|
19
19
|
assert_equal 2, @fluxor.versions.length
|
20
20
|
assert_nil @fluxor.versions[0].reify
|
21
21
|
assert_equal 'Some text.', @fluxor.versions[1].reify.name
|
22
22
|
|
23
|
-
# Check values are stored as YAML
|
23
|
+
# Check values are stored as `YAML`.
|
24
24
|
assert_equal @original_fluxor_attributes, YAML.load(@fluxor.versions[1].object)
|
25
25
|
# This test can't consistently pass in Ruby1.8 because hashes do no preserve order, which means the order of the
|
26
|
-
# attributes in the YAML can't be ensured.
|
26
|
+
# attributes in the `YAML` can't be ensured.
|
27
27
|
if RUBY_VERSION.to_f >= 1.9
|
28
28
|
assert_equal YAML.dump(@original_fluxor_attributes), @fluxor.versions[1].object
|
29
29
|
end
|
@@ -33,7 +33,7 @@ class SerializerTest < ActiveSupport::TestCase
|
|
33
33
|
context 'JSON Serializer' do
|
34
34
|
setup do
|
35
35
|
PaperTrail.configure do |config|
|
36
|
-
config.serializer = PaperTrail::Serializers::
|
36
|
+
config.serializer = PaperTrail::Serializers::JSON
|
37
37
|
end
|
38
38
|
|
39
39
|
Fluxor.instance_eval <<-END
|
@@ -46,7 +46,7 @@ class SerializerTest < ActiveSupport::TestCase
|
|
46
46
|
end
|
47
47
|
|
48
48
|
teardown do
|
49
|
-
PaperTrail.config.serializer = PaperTrail::Serializers::
|
49
|
+
PaperTrail.config.serializer = PaperTrail::Serializers::YAML
|
50
50
|
end
|
51
51
|
|
52
52
|
should 'reify with JSON serializer' do
|
@@ -88,7 +88,7 @@ class SerializerTest < ActiveSupport::TestCase
|
|
88
88
|
end
|
89
89
|
|
90
90
|
teardown do
|
91
|
-
PaperTrail.config.serializer = PaperTrail::Serializers::
|
91
|
+
PaperTrail.config.serializer = PaperTrail::Serializers::YAML
|
92
92
|
end
|
93
93
|
|
94
94
|
should 'reify with custom serializer' do
|