paper_trail 1.6.4 → 1.6.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -541,6 +541,7 @@ Many thanks to:
541
541
  * Danny Trelogan
542
542
  * [Mikl Kurkov](http://github.com/mkurkov)
543
543
  * [Franco Catena](https://github.com/francocatena)
544
+ * [Emmanuel](https://github.com/emmanuel)
544
545
 
545
546
 
546
547
  ## Inspirations
@@ -3,9 +3,6 @@ module PaperTrail
3
3
 
4
4
  def self.included(base)
5
5
  base.send :extend, ClassMethods
6
-
7
- # The version this instance was reified from.
8
- attr_accessor :version
9
6
  end
10
7
 
11
8
 
@@ -24,6 +21,9 @@ module PaperTrail
24
21
  # any more ActiveRecord models than we have to.
25
22
  send :include, InstanceMethods
26
23
 
24
+ # The version this instance was reified from.
25
+ attr_accessor :version
26
+
27
27
  cattr_accessor :ignore
28
28
  self.ignore = (options[:ignore] || []).map &:to_s
29
29
 
@@ -71,14 +71,14 @@ module PaperTrail
71
71
  def version_at(timestamp)
72
72
  # Because a version stores how its object looked *before* the change,
73
73
  # we need to look for the first version created *after* the timestamp.
74
- version = versions.first :conditions => ['created_at > ?', timestamp], :order => 'created_at ASC, id ASC'
74
+ version = versions.after(timestamp).first
75
75
  version ? version.reify : self
76
76
  end
77
77
 
78
78
  # Returns the object (not a Version) as it was most recently.
79
79
  def previous_version
80
- last_version = version ? version.previous : versions.last
81
- last_version.try :reify
80
+ preceding_version = version ? version.previous : versions.last
81
+ preceding_version.try :reify
82
82
  end
83
83
 
84
84
  # Returns the object (not a Version) as it became next.
@@ -98,7 +98,7 @@ module PaperTrail
98
98
  end
99
99
 
100
100
  def record_update
101
- if switched_on? && changed_and_we_care?
101
+ if switched_on? && changed_notably?
102
102
  versions.build merge_metadata(:event => 'update',
103
103
  :object => object_to_string(item_before_change),
104
104
  :whodunnit => PaperTrail.whodunnit)
@@ -117,27 +117,36 @@ module PaperTrail
117
117
  def merge_metadata(data)
118
118
  # First we merge the model-level metadata in `meta`.
119
119
  meta.each do |k,v|
120
- data[k] = v.respond_to?(:call) ? v.call(self) : v
120
+ data[k] =
121
+ if v.respond_to?(:call)
122
+ v.call(self)
123
+ elsif v.is_a?(Symbol) && respond_to?(v)
124
+ send(v)
125
+ else
126
+ v
127
+ end
121
128
  end
122
129
  # Second we merge any extra data from the controller (if available).
123
130
  data.merge(PaperTrail.controller_info || {})
124
131
  end
125
132
 
126
133
  def item_before_change
127
- previous = self.clone
128
- previous.id = id
129
- changes.each do |attr, ary|
130
- previous.send :write_attribute, attr.to_sym, ary.first
134
+ self.clone.tap do |previous|
135
+ previous.id = id
136
+ changed_attributes.each { |attr, before| previous[attr] = before }
131
137
  end
132
- previous
133
138
  end
134
139
 
135
140
  def object_to_string(object)
136
141
  object.attributes.to_yaml
137
142
  end
138
143
 
139
- def changed_and_we_care?
140
- changed? and !(changed - self.class.ignore).empty?
144
+ def changed_notably?
145
+ notably_changed.any?
146
+ end
147
+
148
+ def notably_changed
149
+ changed - self.class.ignore
141
150
  end
142
151
 
143
152
  # Returns `true` if PaperTrail is globally enabled and active for this class,
@@ -2,6 +2,26 @@ class Version < ActiveRecord::Base
2
2
  belongs_to :item, :polymorphic => true
3
3
  validates_presence_of :event
4
4
 
5
+ named_scope :with_item_keys, lambda { |item_type, item_id| {
6
+ :conditions => { :item_type => item_type, :item_id => item_id }
7
+ } }
8
+
9
+ named_scope :subsequent, lambda { |version| {
10
+ :conditions => ["id > ?", version.is_a?(ActiveRecord::Base) ? version.id : version],
11
+ :order => "id ASC",
12
+ } }
13
+
14
+ named_scope :preceding, lambda { |version| {
15
+ :conditions => ["id < ?", version.is_a?(ActiveRecord::Base) ? version.id : version],
16
+ :order => "id DESC",
17
+ } }
18
+
19
+ named_scope :after, lambda { |timestamp| {
20
+ :conditions => ['created_at > ?', timestamp],
21
+ # TODO: is this :order necessary, considering its presence on the has_many :versions association?
22
+ :order => 'created_at ASC, id ASC'
23
+ } }
24
+
5
25
  # Restore the item from this version.
6
26
  #
7
27
  # This will automatically restore all :has_one associations as they were "at the time",
@@ -69,19 +89,20 @@ class Version < ActiveRecord::Base
69
89
  whodunnit
70
90
  end
71
91
 
92
+ def sibling_versions
93
+ Version.with_item_keys(item_type, item_id)
94
+ end
95
+
72
96
  def next
73
- Version.first :conditions => ["id > ? AND item_type = ? AND item_id = ?", id, item_type, item_id],
74
- :order => 'id ASC'
97
+ sibling_versions.subsequent(self).first
75
98
  end
76
99
 
77
100
  def previous
78
- Version.first :conditions => ["id < ? AND item_type = ? AND item_id = ?", id, item_type, item_id],
79
- :order => 'id DESC'
101
+ sibling_versions.preceding(self).first
80
102
  end
81
103
 
82
104
  def index
83
- Version.all(:conditions => ["item_type = ? AND item_id = ?", item_type, item_id],
84
- :order => 'id ASC').index(self)
105
+ sibling_versions.all(:select => :id, :order => "id ASC").map(&:id).index(self.id)
85
106
  end
86
107
 
87
108
  private
@@ -1,3 +1,3 @@
1
1
  module PaperTrail
2
- VERSION = '1.6.4'
2
+ VERSION = '1.6.5'
3
3
  end
data/paper_trail.gemspec CHANGED
@@ -21,7 +21,10 @@ Gem::Specification.new do |s|
21
21
  s.add_development_dependency 'shoulda', '2.10.3'
22
22
  s.add_development_dependency 'activesupport', '~> 2.3'
23
23
  s.add_development_dependency 'sqlite3-ruby', '~> 1.2'
24
+ # Repeated here to make bundler happy
25
+ s.add_development_dependency 'activerecord', '~> 2.3'
26
+ s.add_development_dependency 'actionpack', '~> 2.3'
24
27
 
25
- s.add_dependency 'activerecord', '>= 2.3'
26
- s.add_dependency 'actionpack', '>= 2.3'
28
+ s.add_dependency 'activerecord', '~> 2.3'
29
+ s.add_dependency 'actionpack', '~> 2.3'
27
30
  end
@@ -21,8 +21,13 @@ end
21
21
  class Article < ActiveRecord::Base
22
22
  has_paper_trail :ignore => [:title],
23
23
  :meta => {:answer => 42,
24
+ :action => :action_data_provider_method,
24
25
  :question => Proc.new { "31 + 11 = #{31 + 11}" },
25
26
  :article_id => Proc.new { |article| article.id } }
27
+
28
+ def action_data_provider_method
29
+ self.object_id.to_s
30
+ end
26
31
  end
27
32
 
28
33
  class Book < ActiveRecord::Base
@@ -528,6 +533,10 @@ class HasPaperTrailModelTest < Test::Unit::TestCase
528
533
  assert_equal @article.id, @article.versions.last.article_id
529
534
  end
530
535
 
536
+ should 'store dynamic meta data based on a method of the item' do
537
+ assert_equal @article.action_data_provider_method, @article.versions.last.action
538
+ end
539
+
531
540
 
532
541
  context 'and updated' do
533
542
  setup { @article.update_attributes! :content => 'Better text.' }
data/test/schema.rb CHANGED
@@ -25,6 +25,7 @@ ActiveRecord::Schema.define(:version => 0) do
25
25
 
26
26
  # Metadata columns.
27
27
  t.integer :answer
28
+ t.string :action
28
29
  t.string :question
29
30
  t.integer :article_id
30
31
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paper_trail
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 6
9
- - 4
10
- version: 1.6.4
9
+ - 5
10
+ version: 1.6.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andy Stewart
@@ -15,14 +15,13 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-19 00:00:00 +00:00
18
+ date: 2011-02-08 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: bundler
23
- type: :development
24
23
  prerelease: false
25
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
26
25
  none: false
27
26
  requirements:
28
27
  - - ~>
@@ -32,12 +31,12 @@ dependencies:
32
31
  - 1
33
32
  - 0
34
33
  version: "1.0"
35
- requirement: *id001
34
+ type: :development
35
+ version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- type: :development
39
38
  prerelease: false
40
- version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ requirement: &id002 !ruby/object:Gem::Requirement
41
40
  none: false
42
41
  requirements:
43
42
  - - "="
@@ -48,12 +47,12 @@ dependencies:
48
47
  - 8
49
48
  - 7
50
49
  version: 0.8.7
51
- requirement: *id002
50
+ type: :development
51
+ version_requirements: *id002
52
52
  - !ruby/object:Gem::Dependency
53
53
  name: shoulda
54
- type: :development
55
54
  prerelease: false
56
- version_requirements: &id003 !ruby/object:Gem::Requirement
55
+ requirement: &id003 !ruby/object:Gem::Requirement
57
56
  none: false
58
57
  requirements:
59
58
  - - "="
@@ -64,12 +63,12 @@ dependencies:
64
63
  - 10
65
64
  - 3
66
65
  version: 2.10.3
67
- requirement: *id003
66
+ type: :development
67
+ version_requirements: *id003
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: activesupport
70
- type: :development
71
70
  prerelease: false
72
- version_requirements: &id004 !ruby/object:Gem::Requirement
71
+ requirement: &id004 !ruby/object:Gem::Requirement
73
72
  none: false
74
73
  requirements:
75
74
  - - ~>
@@ -79,12 +78,12 @@ dependencies:
79
78
  - 2
80
79
  - 3
81
80
  version: "2.3"
82
- requirement: *id004
81
+ type: :development
82
+ version_requirements: *id004
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: sqlite3-ruby
85
- type: :development
86
85
  prerelease: false
87
- version_requirements: &id005 !ruby/object:Gem::Requirement
86
+ requirement: &id005 !ruby/object:Gem::Requirement
88
87
  none: false
89
88
  requirements:
90
89
  - - ~>
@@ -94,37 +93,68 @@ dependencies:
94
93
  - 1
95
94
  - 2
96
95
  version: "1.2"
97
- requirement: *id005
96
+ type: :development
97
+ version_requirements: *id005
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: activerecord
100
- type: :runtime
101
100
  prerelease: false
102
- version_requirements: &id006 !ruby/object:Gem::Requirement
101
+ requirement: &id006 !ruby/object:Gem::Requirement
103
102
  none: false
104
103
  requirements:
105
- - - ">="
104
+ - - ~>
106
105
  - !ruby/object:Gem::Version
107
106
  hash: 5
108
107
  segments:
109
108
  - 2
110
109
  - 3
111
110
  version: "2.3"
112
- requirement: *id006
111
+ type: :development
112
+ version_requirements: *id006
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: actionpack
115
+ prerelease: false
116
+ requirement: &id007 !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ~>
120
+ - !ruby/object:Gem::Version
121
+ hash: 5
122
+ segments:
123
+ - 2
124
+ - 3
125
+ version: "2.3"
126
+ type: :development
127
+ version_requirements: *id007
128
+ - !ruby/object:Gem::Dependency
129
+ name: activerecord
130
+ prerelease: false
131
+ requirement: &id008 !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ~>
135
+ - !ruby/object:Gem::Version
136
+ hash: 5
137
+ segments:
138
+ - 2
139
+ - 3
140
+ version: "2.3"
115
141
  type: :runtime
142
+ version_requirements: *id008
143
+ - !ruby/object:Gem::Dependency
144
+ name: actionpack
116
145
  prerelease: false
117
- version_requirements: &id007 !ruby/object:Gem::Requirement
146
+ requirement: &id009 !ruby/object:Gem::Requirement
118
147
  none: false
119
148
  requirements:
120
- - - ">="
149
+ - - ~>
121
150
  - !ruby/object:Gem::Version
122
151
  hash: 5
123
152
  segments:
124
153
  - 2
125
154
  - 3
126
155
  version: "2.3"
127
- requirement: *id007
156
+ type: :runtime
157
+ version_requirements: *id009
128
158
  description: Track changes to your models' data. Good for auditing or versioning.
129
159
  email: boss@airbladesoftware.com
130
160
  executables: []