paper_trail 2.7.2 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +13 -4
  5. data/CHANGELOG.md +15 -0
  6. data/README.md +109 -38
  7. data/Rakefile +9 -3
  8. data/gemfiles/3.0.gemfile +31 -0
  9. data/lib/generators/paper_trail/install_generator.rb +7 -4
  10. data/lib/paper_trail.rb +15 -9
  11. data/lib/paper_trail/cleaner.rb +34 -0
  12. data/lib/paper_trail/frameworks/cucumber.rb +31 -0
  13. data/lib/paper_trail/frameworks/rails.rb +79 -0
  14. data/lib/paper_trail/frameworks/rspec.rb +24 -0
  15. data/lib/paper_trail/frameworks/rspec/extensions.rb +20 -0
  16. data/lib/paper_trail/frameworks/sinatra.rb +31 -0
  17. data/lib/paper_trail/has_paper_trail.rb +22 -20
  18. data/lib/paper_trail/version.rb +188 -161
  19. data/lib/paper_trail/version_number.rb +1 -1
  20. data/paper_trail.gemspec +10 -6
  21. data/spec/models/widget_spec.rb +13 -0
  22. data/spec/paper_trail_spec.rb +47 -0
  23. data/spec/spec_helper.rb +41 -0
  24. data/test/dummy/app/controllers/widgets_controller.rb +10 -2
  25. data/test/dummy/app/models/protected_widget.rb +1 -1
  26. data/test/dummy/app/models/widget.rb +6 -1
  27. data/test/dummy/app/versions/post_version.rb +1 -1
  28. data/test/dummy/config/application.rb +5 -6
  29. data/test/dummy/config/environments/development.rb +6 -4
  30. data/test/dummy/config/environments/production.rb +6 -0
  31. data/test/dummy/config/environments/test.rb +4 -4
  32. data/test/dummy/config/initializers/paper_trail.rb +4 -2
  33. data/test/functional/controller_test.rb +2 -2
  34. data/test/functional/modular_sinatra_test.rb +44 -0
  35. data/test/functional/sinatra_test.rb +45 -0
  36. data/test/functional/thread_safety_test.rb +1 -1
  37. data/test/paper_trail_test.rb +2 -2
  38. data/test/unit/cleaner_test.rb +143 -0
  39. data/test/unit/inheritance_column_test.rb +3 -3
  40. data/test/unit/model_test.rb +74 -55
  41. data/test/unit/protected_attrs_test.rb +12 -7
  42. data/test/unit/timestamp_test.rb +2 -2
  43. data/test/unit/version_test.rb +37 -20
  44. metadata +86 -26
  45. data/lib/paper_trail/controller.rb +0 -75
@@ -1,3 +1,3 @@
1
1
  module PaperTrail
2
- VERSION = '2.7.2'
2
+ VERSION = '3.0.0.beta1'
3
3
  end
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.summary = "Track changes to your models' data. Good for auditing or versioning."
8
8
  s.description = s.summary
9
9
  s.homepage = 'http://github.com/airblade/paper_trail'
10
- s.authors = ['Andy Stewart']
10
+ s.authors = ['Andy Stewart', 'Ben Atkins']
11
11
  s.email = 'boss@airbladesoftware.com'
12
12
 
13
13
  s.files = `git ls-files`.split("\n")
@@ -15,17 +15,21 @@ Gem::Specification.new do |s|
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
16
  s.require_paths = ['lib']
17
17
 
18
- s.add_dependency 'railties', '~> 3.0'
19
- s.add_dependency 'activerecord', '~> 3.0'
18
+ s.add_dependency 'activerecord', ['>= 3.0', '< 5.0']
20
19
 
21
20
  s.add_development_dependency 'rake'
22
- s.add_development_dependency 'shoulda', '~> 3.3'
23
- s.add_development_dependency 'shoulda-matchers', '~> 1.5'
21
+ s.add_development_dependency 'shoulda', '~> 3.5'
22
+ # s.add_development_dependency 'shoulda-matchers', '~> 1.5'
24
23
  s.add_development_dependency 'ffaker', '>= 1.15'
24
+ s.add_development_dependency 'railties', ['>= 3.0', '< 5.0']
25
+ s.add_development_dependency 'sinatra', '~> 1.0'
26
+ s.add_development_dependency 'rack-test', '>= 0.6'
27
+ s.add_development_dependency 'rspec-rails', '~> 2.14'
28
+
25
29
  # JRuby support for the test ENV
26
30
  unless defined?(JRUBY_VERSION)
27
31
  s.add_development_dependency 'sqlite3', '~> 1.2'
28
32
  else
29
- s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', '~> 1.2.9'
33
+ s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', ['>= 1.3.0.rc1', '< 1.4']
30
34
  end
31
35
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Widget do
4
+ it { should be_versioned }
5
+
6
+ context 'be_versioned matcher', :versioning => true do
7
+ it 'should respond to be_versioned' do
8
+ widget = Widget.create :name => 'Bob', :an_integer => 1
9
+ widget.should be_versioned
10
+ widget.versions.size.should == 1
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe "PaperTrail RSpec Helper" do
4
+ describe :enabled do
5
+ context 'default' do
6
+ it 'should have versioning off by default' do
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
16
+ end
17
+
18
+ context 'versioning: true', :versioning => true do
19
+ it 'should have versioning on by default' do
20
+ ::PaperTrail.should be_enabled
21
+ end
22
+ it 'should keep versioning on after a with_versioning block' do
23
+ ::PaperTrail.should be_enabled
24
+ with_versioning do
25
+ ::PaperTrail.should be_enabled
26
+ end
27
+ ::PaperTrail.should be_enabled
28
+ end
29
+ end
30
+ end
31
+
32
+ describe :whodunnit do
33
+ before(:all) { ::PaperTrail.whodunnit = 'foobar' }
34
+
35
+ it "should get set to `nil` by default" do
36
+ ::PaperTrail.whodunnit.should be_nil
37
+ end
38
+ end
39
+
40
+ describe :controller_info do
41
+ before(:all) { ::PaperTrail.controller_info = {:foo => 'bar'} }
42
+
43
+ it "should get set to an empty hash before each test" do
44
+ ::PaperTrail.controller_info.should == {}
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+ require File.expand_path('../../test/dummy/config/environment', __FILE__)
3
+
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+
7
+ # Requires supporting ruby files with custom matchers and macros, etc,
8
+ # in spec/support/ and its subdirectories.
9
+ Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
10
+
11
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+
15
+ # ## Mock Framework
16
+ #
17
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
18
+ #
19
+ # config.mock_with :mocha
20
+ # config.mock_with :flexmock
21
+ # config.mock_with :rr
22
+
23
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
24
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
25
+
26
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
27
+ # examples within a transaction, remove the following line or assign false
28
+ # instead of true.
29
+ config.use_transactional_fixtures = true
30
+
31
+ # If true, the base class of anonymous controllers will be inferred
32
+ # automatically. This will be the default behavior in future versions of
33
+ # rspec-rails.
34
+ config.infer_base_class_for_anonymous_controllers = false
35
+
36
+ # Run specs in random order to surface order dependencies. If you find an
37
+ # order dependency and want to debug it, you can fix the order by providing
38
+ # the seed, which is printed after each run.
39
+ # --seed 1234
40
+ config.order = 'random'
41
+ end
@@ -5,13 +5,21 @@ class WidgetsController < ApplicationController
5
5
  end
6
6
 
7
7
  def create
8
- @widget = Widget.create params[:widget]
8
+ if PaperTrail.active_record_protected_attributes?
9
+ @widget = Widget.create params[:widget]
10
+ else
11
+ @widget = Widget.create params[:widget].permit!
12
+ end
9
13
  head :ok
10
14
  end
11
15
 
12
16
  def update
13
17
  @widget = Widget.find params[:id]
14
- @widget.update_attributes params[:widget]
18
+ if PaperTrail.active_record_protected_attributes?
19
+ @widget.update_attributes params[:widget]
20
+ else
21
+ @widget.update_attributes params[:widget].permit!
22
+ end
15
23
  head :ok
16
24
  end
17
25
 
@@ -1,3 +1,3 @@
1
1
  class ProtectedWidget < Widget
2
- attr_accessible :name, :a_text
2
+ attr_accessible :name, :a_text if ::PaperTrail.active_record_protected_attributes?
3
3
  end
@@ -1,5 +1,10 @@
1
1
  class Widget < ActiveRecord::Base
2
2
  has_paper_trail
3
3
  has_one :wotsit
4
- has_many :fluxors, :order => :name
4
+
5
+ if ActiveRecord::VERSION::STRING.to_f >= 4.0 # `has_many` syntax for specifying order uses a lambda in Rails 4
6
+ has_many :fluxors, lambda { order(:name) }
7
+ else
8
+ has_many :fluxors, :order => :name
9
+ end
5
10
  end
@@ -1,3 +1,3 @@
1
- class PostVersion < Version
1
+ class PostVersion < PaperTrail::Version
2
2
  self.table_name = 'post_versions'
3
3
  end
@@ -1,9 +1,8 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
- require "active_model/railtie"
3
+ # Pick the frameworks you want:
4
4
  require "active_record/railtie"
5
5
  require "action_controller/railtie"
6
- require "action_view/railtie"
7
6
 
8
7
  Bundler.require(:default, Rails.env) if defined?(Bundler)
9
8
  require 'paper_trail'
@@ -50,15 +49,15 @@ module Dummy
50
49
  # This will create an empty whitelist of attributes available for mass-assignment for all models
51
50
  # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
52
51
  # parameters by using an attr_accessible or attr_protected declaration.
53
- #
54
- # This is uncommented in new rails apps by default but for our testing purposes its more convenient
55
- # to leave it commented out.
56
- # config.active_record.whitelist_attributes = true
52
+ config.active_record.whitelist_attributes = false if ::PaperTrail.active_record_protected_attributes?
57
53
 
58
54
  # Enable the asset pipeline
59
55
  config.assets.enabled = false
60
56
 
61
57
  # Version of your assets, change this if you want to expire all your assets
62
58
  # config.assets.version = '1.0'
59
+
60
+ # Rails 4 key for generating secret key
61
+ config.secret_key_base = 'A fox regularly kicked the screaming pile of biscuits.'
63
62
  end
64
63
  end
@@ -6,8 +6,8 @@ Dummy::Application.configure do
6
6
  # since you don't have to restart the web server when you make code changes.
7
7
  config.cache_classes = false
8
8
 
9
- # Log error messages when you accidentally call methods on nil.
10
- config.whiny_nils = true
9
+ # Do not eager load code on boot.
10
+ config.eager_load = false
11
11
 
12
12
  # Show full error reports and disable caching
13
13
  config.consider_all_requests_local = true
@@ -23,7 +23,7 @@ Dummy::Application.configure do
23
23
  config.action_dispatch.best_standards_support = :builtin
24
24
 
25
25
  # Raise exception on mass assignment protection for Active Record models
26
- config.active_record.mass_assignment_sanitizer = :strict
26
+ config.active_record.mass_assignment_sanitizer = :strict if ::PaperTrail.active_record_protected_attributes?
27
27
 
28
28
  # Log the query plan for queries taking more than this (works
29
29
  # with SQLite, MySQL, and PostgreSQL)
@@ -32,7 +32,9 @@ Dummy::Application.configure do
32
32
  # Do not compress assets
33
33
  config.assets.compress = false
34
34
 
35
- # Expands the lines which load the assets
35
+ # Debug mode disables concatenation and preprocessing of assets.
36
+ # This option may cause significant delays in view rendering with a large
37
+ # number of complex assets.
36
38
  config.assets.debug = true
37
39
  end
38
40
 
@@ -4,6 +4,12 @@ Dummy::Application.configure do
4
4
  # Code is not reloaded between requests
5
5
  config.cache_classes = true
6
6
 
7
+ # Eager load code on boot. This eager loads most of Rails and
8
+ # your application in memory, allowing both thread web servers
9
+ # and those relying on copy on write to perform better.
10
+ # Rake tasks automatically ignore this option for performance.
11
+ config.eager_load = true
12
+
7
13
  # Full error reports are disabled and caching is turned on
8
14
  config.consider_all_requests_local = false
9
15
  config.action_controller.perform_caching = true
@@ -7,13 +7,13 @@ Dummy::Application.configure do
7
7
  # and recreated between test runs. Don't rely on the data there!
8
8
  config.cache_classes = true
9
9
 
10
+ # Eager loads all registered namespaces
11
+ config.eager_load = true
12
+
10
13
  # Configure static asset server for tests with Cache-Control for performance
11
14
  config.serve_static_assets = true
12
15
  config.static_cache_control = "public, max-age=3600"
13
16
 
14
- # Log error messages when you accidentally call methods on nil
15
- config.whiny_nils = true
16
-
17
17
  # Show full error reports and disable caching
18
18
  config.consider_all_requests_local = true
19
19
  config.action_controller.perform_caching = false
@@ -30,7 +30,7 @@ Dummy::Application.configure do
30
30
  # config.action_mailer.delivery_method = :test
31
31
 
32
32
  # Raise exception on mass assignment protection for Active Record models
33
- config.active_record.mass_assignment_sanitizer = :strict
33
+ config.active_record.mass_assignment_sanitizer = :strict if ::PaperTrail.active_record_protected_attributes?
34
34
 
35
35
  # Print deprecation notices to the stderr
36
36
  config.active_support.deprecation = :stderr
@@ -1,3 +1,5 @@
1
- class Version < ActiveRecord::Base
2
- attr_accessible :created_at, :updated_at, :answer, :action, :question, :article_id, :ip, :user_agent, :title
1
+ module PaperTrail
2
+ class Version < ActiveRecord::Base
3
+ attr_accessible :created_at, :updated_at, :answer, :action, :question, :article_id, :ip, :user_agent, :title if ::PaperTrail.active_record_protected_attributes?
4
+ end
3
5
  end
@@ -34,7 +34,7 @@ class ControllerTest < ActionController::TestCase
34
34
  assert_equal 0, w.versions.length
35
35
  delete :destroy, :id => w.id
36
36
  widget = assigns(:widget)
37
- assert_equal 0, Version.with_item_keys('Widget', w.id).size
37
+ assert_equal 0, PaperTrail::Version.with_item_keys('Widget', w.id).size
38
38
  end
39
39
 
40
40
  test 'create' do
@@ -62,7 +62,7 @@ class ControllerTest < ActionController::TestCase
62
62
  assert_equal 1, w.versions.length
63
63
  delete :destroy, :id => w.id
64
64
  widget = assigns(:widget)
65
- versions_for_widget = Version.with_item_keys('Widget', w.id)
65
+ versions_for_widget = PaperTrail::Version.with_item_keys('Widget', w.id)
66
66
  assert_equal 2, versions_for_widget.length
67
67
  assert_equal 153, versions_for_widget.last.whodunnit.to_i
68
68
  assert_equal '127.0.0.1', versions_for_widget.last.ip
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+ require 'sinatra/base'
3
+
4
+ # --- Tests for modular `Sinatra::Base` style ----
5
+ class BaseApp < Sinatra::Base
6
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => File.expand_path('../../dummy/db/test.sqlite3', __FILE__))
7
+ register Sinatra::PaperTrail
8
+
9
+ get '/test' do
10
+ Widget.create!(:name => 'foo')
11
+ 'Hello'
12
+ end
13
+
14
+ def current_user
15
+ 'foobar'
16
+ end
17
+ end
18
+
19
+ class ModularSinatraTest < ActionDispatch::IntegrationTest
20
+ include Rack::Test::Methods
21
+
22
+ def app
23
+ @app ||= BaseApp
24
+ end
25
+
26
+ test 'baseline' do
27
+ assert_nil Widget.first
28
+ assert_nil Widget.create.versions.first.whodunnit
29
+ end
30
+
31
+ context "`PaperTrail::Sinatra` in a `Sinatra::Base` application" do
32
+
33
+ should "sets the `user_for_paper_trail` from the `current_user` method" do
34
+ get '/test'
35
+ assert_equal 'Hello', last_response.body
36
+ widget = Widget.first
37
+ assert_not_nil widget
38
+ assert_equal 'foo', widget.name
39
+ assert_equal 1, widget.versions.size
40
+ assert_equal 'foobar', widget.versions.first.whodunnit
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,45 @@
1
+ require 'test_helper'
2
+ # require 'sinatra/main'
3
+
4
+ # --- Tests for non-modular `Sinatra::Application` style ----
5
+ class Sinatra::Application
6
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => File.expand_path('../../dummy/db/test.sqlite3', __FILE__))
7
+ register Sinatra::PaperTrail # we shouldn't actually need this line if I'm not mistaken but the tests seem to fail without it ATM
8
+
9
+ get '/test' do
10
+ Widget.create!(:name => 'bar')
11
+ 'Hai'
12
+ end
13
+
14
+ def current_user
15
+ 'raboof'
16
+ end
17
+
18
+ end
19
+
20
+ class SinatraTest < ActionDispatch::IntegrationTest
21
+ include Rack::Test::Methods
22
+
23
+ def app
24
+ @app ||= Sinatra::Application
25
+ end
26
+
27
+ test 'baseline' do
28
+ assert_nil Widget.first
29
+ assert_nil Widget.create.versions.first.whodunnit
30
+ end
31
+
32
+ context "`PaperTrail::Sinatra` in a `Sinatra::Application` application" do
33
+
34
+ should "sets the `user_for_paper_trail` from the `current_user` method" do
35
+ get '/test'
36
+ assert_equal 'Hai', last_response.body
37
+ widget = Widget.first
38
+ assert_not_nil widget
39
+ assert_equal 'bar', widget.name
40
+ assert_equal 1, widget.versions.size
41
+ assert_equal 'raboof', widget.versions.first.whodunnit
42
+ end
43
+
44
+ end
45
+ end
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class ThreadSafetyTest < ActionController::TestCase
4
- should "be thread safe" do
4
+ test "be thread safe" do
5
5
  blocked = true
6
6
 
7
7
  slow_thread = Thread.new do
@@ -2,7 +2,7 @@ require 'test_helper'
2
2
 
3
3
  class PaperTrailTest < ActiveSupport::TestCase
4
4
  test 'Sanity test' do
5
- assert_kind_of Module, PaperTrail
5
+ assert_kind_of Module, PaperTrail::Version
6
6
  end
7
7
 
8
8
  test 'create with plain model class' do
@@ -21,7 +21,7 @@ class PaperTrailTest < ActiveSupport::TestCase
21
21
  widget = Widget.create
22
22
  assert_equal 1, widget.versions.length
23
23
  widget.destroy
24
- versions_for_widget = Version.with_item_keys('Widget', widget.id)
24
+ versions_for_widget = PaperTrail::Version.with_item_keys('Widget', widget.id)
25
25
  assert_equal 2, versions_for_widget.length
26
26
  end
27
27
  end
@@ -0,0 +1,143 @@
1
+ require 'test_helper'
2
+
3
+ class PaperTrailCleanerTest < ActiveSupport::TestCase
4
+
5
+ setup do
6
+ @animals = [@animal = Animal.new, @dog = Dog.new, @cat = Cat.new]
7
+ @animals.each do |animal|
8
+ 3.times { animal.update_attribute(:name, Faker::Name.name) }
9
+ end
10
+ end
11
+
12
+ test 'Baseline' do
13
+ assert_equal 9, PaperTrail::Version.count
14
+ @animals.each { |animal| assert_equal 3, animal.versions.size }
15
+ end
16
+
17
+ context '`clean_versions!` method' do
18
+ should 'be extended by `PaperTrail` module' do
19
+ assert_respond_to PaperTrail, :clean_versions!
20
+ end
21
+
22
+ context 'No options provided' do
23
+ should 'removes extra versions for each item' do
24
+ PaperTrail.clean_versions!
25
+ assert_equal 3, PaperTrail::Version.count
26
+ @animals.each { |animal| assert_equal 1, animal.versions.size }
27
+ end
28
+
29
+ should 'removes the earliest version(s)' do
30
+ most_recent_version_names = @animals.map { |animal| animal.versions.last.reify.name }
31
+ PaperTrail.clean_versions!
32
+ assert_equal most_recent_version_names, @animals.map { |animal| animal.versions.last.reify.name }
33
+ end
34
+ end
35
+
36
+ context '`:keeping` option' do
37
+ should 'modifies the number of versions ommitted from destruction' do
38
+ PaperTrail.clean_versions!(:keeping => 2)
39
+ assert_equal 6, PaperTrail::Version.all.count
40
+ @animals.each { |animal| assert_equal 2, animal.versions.size }
41
+ end
42
+ end
43
+
44
+ context '`:date` option' do
45
+ setup do
46
+ @animal.versions.each { |ver| ver.update_attribute(:created_at, ver.created_at - 1.day) }
47
+ @date = @animal.versions.first.created_at.to_date
48
+ @animal.update_attribute(:name, Faker::Name.name)
49
+ end
50
+
51
+ should 'restrict the versions destroyed to those that were created on the date provided' do
52
+ assert_equal 10, PaperTrail::Version.count
53
+ assert_equal 4, @animal.versions.size
54
+ assert_equal 3, @animal.versions_between(@date, @date + 1.day).size
55
+ PaperTrail.clean_versions!(:date => @date)
56
+ assert_equal 8, PaperTrail::Version.count
57
+ assert_equal 2, @animal.versions(true).size
58
+ assert_equal @date, @animal.versions.first.created_at.to_date
59
+ assert_not_same @date, @animal.versions.last.created_at.to_date
60
+ end
61
+ end
62
+
63
+ context '`:item_id` option' do
64
+ context 'single ID received' do
65
+ should 'restrict the versions destroyed to the versions for the Item with that ID' do
66
+ PaperTrail.clean_versions!(:item_id => @animal.id)
67
+ assert_equal 1, @animal.versions.size
68
+ assert_equal 7, PaperTrail::Version.count
69
+ end
70
+ end
71
+
72
+ context "collection of ID's received" do
73
+ should "restrict the versions destroyed to the versions for the Item with those ID's" do
74
+ PaperTrail.clean_versions!(:item_id => [@animal.id, @dog.id])
75
+ assert_equal 1, @animal.versions.size
76
+ assert_equal 1, @dog.versions.size
77
+ assert_equal 5, PaperTrail::Version.count
78
+ end
79
+ end
80
+ end
81
+
82
+ context 'options combinations' do # additional tests to cover combinations of options
83
+ context '`:date`' do
84
+ setup do
85
+ [@animal, @dog].each do |animal|
86
+ animal.versions.each { |ver| ver.update_attribute(:created_at, ver.created_at - 1.day) }
87
+ animal.update_attribute(:name, Faker::Name.name)
88
+ end
89
+ @date = @animal.versions.first.created_at.to_date
90
+ end
91
+
92
+ should 'Baseline' do
93
+ assert_equal 11, PaperTrail::Version.count
94
+ [@animal, @dog].each do |animal|
95
+ assert_equal 4, animal.versions.size
96
+ assert_equal 3, animal.versions.between(@date, @date+1.day).size
97
+ end
98
+ end
99
+
100
+ context 'and `:keeping`' do
101
+ should 'restrict cleaning properly' do
102
+ PaperTrail.clean_versions!(:date => @date, :keeping => 2)
103
+ [@animal, @dog].each do |animal|
104
+ animal.versions.reload # reload the association to pick up the destructions made by the `Cleaner`
105
+ assert_equal 3, animal.versions.size
106
+ assert_equal 2, animal.versions.between(@date, @date+1.day).size
107
+ end
108
+ assert_equal 9, PaperTrail::Version.count # ensure that the versions for the `@cat` instance wasn't touched
109
+ end
110
+ end
111
+
112
+ context 'and `:item_id`' do
113
+ should 'restrict cleaning properly' do
114
+ PaperTrail.clean_versions!(:date => @date, :item_id => @dog.id)
115
+ @dog.versions.reload # reload the association to pick up the destructions made by the `Cleaner`
116
+ assert_equal 2, @dog.versions.size
117
+ assert_equal 1, @dog.versions.between(@date, @date+1.day).size
118
+ assert_equal 9, PaperTrail::Version.count # ensure the versions for other animals besides `@animal` weren't touched
119
+ end
120
+ end
121
+
122
+ context ', `:item_id`, and `:keeping`' do
123
+ should 'restrict cleaning properly' do
124
+ PaperTrail.clean_versions!(:date => @date, :item_id => @dog.id, :keeping => 2)
125
+ @dog.versions.reload # reload the association to pick up the destructions made by the `Cleaner`
126
+ assert_equal 3, @dog.versions.size
127
+ assert_equal 2, @dog.versions.between(@date, @date+1.day).size
128
+ assert_equal 10, PaperTrail::Version.count # ensure the versions for other animals besides `@animal` weren't touched
129
+ end
130
+ end
131
+ end
132
+
133
+ context '`:keeping` and `:item_id`' do
134
+ should 'restrict cleaning properly' do
135
+ PaperTrail.clean_versions!(:keeping => 2, :item_id => @animal.id)
136
+ assert_equal 2, @animal.versions.size
137
+ assert_equal 8, PaperTrail::Version.count # ensure the versions for other animals besides `@animal` weren't touched
138
+ end
139
+ end
140
+ end
141
+
142
+ end # clean_versions! method
143
+ end