paper_trail 1.4.0 → 1.4.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.
data/README.md CHANGED
@@ -10,6 +10,7 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
10
10
  * Does not store updates which only change attributes you are ignoring.
11
11
  * Allows you to get at every version, including the original, even once destroyed.
12
12
  * Allows you to get at every version even if the schema has since changed.
13
+ * Allows you to get at the version as of a particular time.
13
14
  * Automatically records who was responsible if your controller has a `current_user` method.
14
15
  * Allows you to set who is responsible at model-level (useful for migrations).
15
16
  * Allows you to store arbitrary metadata with each version (useful for filtering versions).
@@ -118,6 +119,13 @@ PaperTrail makes reverting to a previous version easy:
118
119
  >> widget = widget.versions.last.reify # the widget as it was before the update
119
120
  >> widget.save # reverted
120
121
 
122
+ Alternatively you can find the version at a given time:
123
+
124
+ >> widget = widget.version_at(1.day.ago) # the widget as it was one day ago
125
+ >> widget.save # reverted
126
+
127
+ Note `version_at` gives you the object, not a version, so you don't need to call `reify`.
128
+
121
129
  Undeleting is just as simple:
122
130
 
123
131
  >> widget = Widget.find 42
@@ -201,6 +209,11 @@ And on again like this:
201
209
  PaperTrail has a thorough suite of tests. Thanks to [Zachery Hostens](http://github.com/zacheryph) for making them able to run standalone, i.e. without needing PaperTrail to be sitting in a Rails app.
202
210
 
203
211
 
212
+ ## Articles
213
+
214
+ [Keep a Paper Trail with PaperTrail](http://www.linux-mag.com/id/7528), Linux Magazine, 16th September 2009.
215
+
216
+
204
217
  ## Problems
205
218
 
206
219
  Please use GitHub's [issue tracker](http://github.com/airblade/paper_trail/issues).
@@ -211,6 +224,7 @@ Please use GitHub's [issue tracker](http://github.com/airblade/paper_trail/issue
211
224
  Many thanks to:
212
225
 
213
226
  * [Zachery Hostens](http://github.com/zacheryph)
227
+ * [Jeremy Weiskotten](http://github.com/jeremyw)
214
228
 
215
229
 
216
230
  ## Inspirations
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.4.1
data/init.rb CHANGED
@@ -1 +1 @@
1
- # Include hook code here
1
+ require 'paper_trail'
data/install.rb CHANGED
@@ -1 +1 @@
1
- # Install hook code here
1
+ puts 'You have chosen wisely.'
@@ -19,7 +19,7 @@ module PaperTrail
19
19
 
20
20
  cattr_accessor :meta
21
21
  self.meta = options[:meta] || {}
22
-
22
+
23
23
  cattr_accessor :paper_trail_active
24
24
  self.paper_trail_active = true
25
25
 
@@ -63,6 +63,18 @@ module PaperTrail
63
63
  end
64
64
  end
65
65
 
66
+ # Returns the object (not a Version) as it was at the given timestamp.
67
+ def version_at(timestamp)
68
+ # Short-circuit if the current state is applicable.
69
+ return self if self.updated_at <= timestamp
70
+ # Look for the first version created after, rather than before, the
71
+ # timestamp because a version stores how the object looked before the
72
+ # change.
73
+ version = versions.first :conditions => ['created_at > ?', timestamp],
74
+ :order => 'created_at ASC'
75
+ version.reify if version
76
+ end
77
+
66
78
  private
67
79
 
68
80
  def merge_metadata(data)
data/paper_trail.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{paper_trail}
8
- s.version = "1.4.0"
8
+ s.version = "1.4.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andy Stewart"]
12
- s.date = %q{2010-01-06}
12
+ s.date = %q{2010-03-18}
13
13
  s.email = %q{boss@airbladesoftware.com}
14
14
  s.extra_rdoc_files = [
15
15
  "README.md"
@@ -29,9 +29,7 @@ Gem::Specification.new do |s|
29
29
  "lib/paper_trail/has_paper_trail.rb",
30
30
  "lib/paper_trail/version.rb",
31
31
  "paper_trail.gemspec",
32
- "rails/init.rb",
33
32
  "tasks/paper_trail_tasks.rake",
34
- "test/database.yml",
35
33
  "test/paper_trail_controller_test.rb",
36
34
  "test/paper_trail_model_test.rb",
37
35
  "test/paper_trail_schema_test.rb",
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
1
+ require 'test_helper'
2
2
 
3
3
  class ApplicationController < ActionController::Base
4
4
  def rescue_action(e)
@@ -32,10 +32,11 @@ end
32
32
 
33
33
 
34
34
  class PaperTrailControllerTest < ActionController::TestCase #Test::Unit::TestCase
35
+ tests WidgetsController
35
36
  def setup
36
- @controller = WidgetsController.new
37
- @request = ActionController::TestRequest.new
38
- @response = ActionController::TestResponse.new
37
+ #@controller = WidgetsController.new
38
+ #@request = ActionController::TestRequest.new
39
+ #@response = ActionController::TestResponse.new
39
40
 
40
41
  ActionController::Routing::Routes.draw do |map|
41
42
  map.resources :widgets
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
1
+ require 'test_helper'
2
2
 
3
3
  class Widget < ActiveRecord::Base
4
4
  has_paper_trail
@@ -30,7 +30,7 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
30
30
 
31
31
  context 'A record' do
32
32
  setup { @article = Article.create }
33
-
33
+
34
34
  context 'which updates an ignored column' do
35
35
  setup { @article.update_attributes :title => 'My first title' }
36
36
  should_not_change('the number of versions') { Version.count }
@@ -100,7 +100,7 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
100
100
  assert_match /update/i, @widget.versions.last.event
101
101
  end
102
102
 
103
-
103
+
104
104
  context 'and has one associated object' do
105
105
  setup do
106
106
  @wotsit = @widget.create_wotsit :name => 'John'
@@ -356,6 +356,47 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
356
356
  @widget.update_attributes :name => 'Digit'
357
357
  end
358
358
 
359
+ context 'which were created over time' do
360
+ setup do
361
+ @created = 2.days.ago
362
+ @first_update = 1.day.ago
363
+ @second_update = 1.hour.ago
364
+ @widget.versions[0].update_attributes :created_at => @created
365
+ @widget.versions[1].update_attributes :created_at => @first_update
366
+ @widget.versions[2].update_attributes :created_at => @second_update
367
+ @widget.update_attribute :updated_at, @second_update
368
+ end
369
+
370
+ should 'return nil for version_at before it was created' do
371
+ assert_nil @widget.version_at(@created - 1)
372
+ end
373
+
374
+ should 'return how it looked when created for version_at its creation' do
375
+ assert_equal 'Widget', @widget.version_at(@created).name
376
+ end
377
+
378
+ should "return how it looked when created for version_at just before its first update" do
379
+ assert_equal 'Widget', @widget.version_at(@first_update - 1).name
380
+ end
381
+
382
+ should "return how it looked when first updated for version_at its first update" do
383
+ assert_equal 'Fidget', @widget.version_at(@first_update).name
384
+ end
385
+
386
+ should 'return how it looked when first updated for version_at just before its second update' do
387
+ assert_equal 'Fidget', @widget.version_at(@second_update - 1).name
388
+ end
389
+
390
+ should 'return how it looked when subsequently updated for version_at its second update' do
391
+ assert_equal 'Digit', @widget.version_at(@second_update).name
392
+ end
393
+
394
+ should 'return the current object for version_at after latest update' do
395
+ assert_equal 'Digit', @widget.version_at(1.day.from_now).name
396
+ end
397
+ end
398
+
399
+
359
400
  context 'on the first version' do
360
401
  setup { @version = @widget.versions.first }
361
402
 
data/test/test_helper.rb CHANGED
@@ -1,43 +1,37 @@
1
- require 'test/unit'
2
- RAILS_ROOT = File.join(File.dirname(__FILE__), %w{.. .. .. ..})
3
- $:.unshift(File.join(File.dirname(__FILE__), %w{.. lib}))
4
-
5
- unless defined?(ActiveRecord)
6
- if File.directory? RAILS_ROOT + 'config'
7
- puts 'using config/boot.rb'
8
- ENV['RAILS_ENV'] = 'test'
9
- require File.join(RAILS_ROOT, 'config', 'boot.rb')
10
- else
11
- # simply use installed gems if available
12
- puts 'using rubygems'
13
- require 'rubygems'
14
- gem 'actionpack'; gem 'activerecord'; gem 'activesupport'; gem 'rails'
15
- end
1
+ require 'rubygems'
16
2
 
17
- %w(action_pack action_controller active_record active_support initializer).each {|f| require f}
18
- end
3
+ require 'test/unit'
19
4
  require 'shoulda'
20
- require 'paper_trail'
21
-
22
- def connect_to_database
23
- config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
24
- ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
25
5
 
26
- db_adapter = ENV['DB'] || 'sqlite3'
6
+ require 'active_record'
7
+ require 'action_controller'
8
+ require 'action_controller/test_process'
9
+ require 'active_support'
10
+ require 'active_support/test_case'
27
11
 
28
- if db_adapter.nil?
29
- raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
30
- end
12
+ require 'lib/paper_trail'
31
13
 
32
- ActiveRecord::Base.establish_connection(config[db_adapter])
14
+ def connect_to_database
15
+ ActiveRecord::Base.establish_connection(
16
+ :adapter => "sqlite3",
17
+ :database => ":memory:"
18
+ )
19
+ ActiveRecord::Migration.verbose = false
33
20
  end
34
21
 
35
22
  def load_schema
36
23
  connect_to_database
37
- load(File.dirname(__FILE__) + "/schema.rb")
38
- require File.dirname(__FILE__) + '/../rails/init.rb'
24
+ load File.dirname(__FILE__) + '/schema.rb'
39
25
  end
40
26
 
41
27
  def change_schema
42
- load(File.dirname(__FILE__) + "/schema_change.rb")
28
+ load File.dirname(__FILE__) + '/schema_change.rb'
29
+ end
30
+
31
+ class ActiveRecord::Base
32
+ def logger
33
+ @logger ||= Logger.new(nil)
34
+ end
43
35
  end
36
+
37
+ load_schema
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: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Stewart
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-06 00:00:00 +00:00
12
+ date: 2010-03-18 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -36,9 +36,7 @@ files:
36
36
  - lib/paper_trail/has_paper_trail.rb
37
37
  - lib/paper_trail/version.rb
38
38
  - paper_trail.gemspec
39
- - rails/init.rb
40
39
  - tasks/paper_trail_tasks.rake
41
- - test/database.yml
42
40
  - test/paper_trail_controller_test.rb
43
41
  - test/paper_trail_model_test.rb
44
42
  - test/paper_trail_schema_test.rb
data/rails/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'paper_trail'
data/test/database.yml DELETED
@@ -1,18 +0,0 @@
1
- sqlite3:
2
- adapter: sqlite3
3
- database: ":memory:"
4
-
5
- postgresql:
6
- adapter: postgresql
7
- username: postgres
8
- password: postgres
9
- database: paper_trail_plugin_test
10
- min_messages: ERROR
11
-
12
- mysql:
13
- adapter: mysql
14
- host: localhost
15
- username: andy
16
- password:
17
- database: paper_trail_plugin_test
18
- socket: /tmp/mysql.sock