Namespacing version class under the PaperTrail module. Fix #165
This commit is contained in:
parent
9703df7705
commit
7bc537a45a
30
README.md
30
README.md
|
@ -72,7 +72,7 @@ Widget.paper_trail_off
|
||||||
Widget.paper_trail_on
|
Widget.paper_trail_on
|
||||||
```
|
```
|
||||||
|
|
||||||
And a `Version` instance has these methods:
|
And a `PaperTrail::Version` instance has these methods:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# Returns the item restored from this version.
|
# Returns the item restored from this version.
|
||||||
|
@ -124,7 +124,7 @@ This gives you a `versions` method which returns the paper trail of changes to y
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
>> widget = Widget.find 42
|
>> widget = Widget.find 42
|
||||||
>> widget.versions # [<Version>, <Version>, ...]
|
>> widget.versions # [<PaperTrail::Version>, <PaperTrail::Version>, ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
Once you have a version, you can find out what happened:
|
Once you have a version, you can find out what happened:
|
||||||
|
@ -193,7 +193,7 @@ class Article < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
You may also have the `Version` model save a custom string in it's `event` field instead of the typical `create`, `update`, `destroy`.
|
You may also have the `PaperTrail::Version` model save a custom string in it's `event` field instead of the typical `create`, `update`, `destroy`.
|
||||||
PaperTrail supplies a custom accessor method called `paper_trail_event`, which it will attempt to use to fill the `event` field before
|
PaperTrail supplies a custom accessor method called `paper_trail_event`, which it will attempt to use to fill the `event` field before
|
||||||
falling back on one of the default events.
|
falling back on one of the default events.
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ class Article < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
This means that changes to just the `title` or `rating` will not store another version of the article. It does not mean that the `title` and `rating` attributes will be ignored if some other change causes a new `Version` to be created. For example:
|
This means that changes to just the `title` or `rating` will not store another version of the article. It does not mean that the `title` and `rating` attributes will be ignored if some other change causes a new `PaperTrail::Version` to be created. For example:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
>> a = Article.create
|
>> a = Article.create
|
||||||
|
@ -267,7 +267,7 @@ This means that only changes to the `title` will save a version of the article:
|
||||||
|
|
||||||
Passing both `:ignore` and `:only` options will result in the article being saved if a changed attribute is included in `:only` but not in `:ignore`.
|
Passing both `:ignore` and `:only` options will result in the article being saved if a changed attribute is included in `:only` but not in `:ignore`.
|
||||||
|
|
||||||
You can skip fields altogether with the `:skip` option. As with `:ignore`, updates to these fields will not create a new `Version`. In addition, these fields will not be included in the serialised version of the object whenever a new `Version` is created.
|
You can skip fields altogether with the `:skip` option. As with `:ignore`, updates to these fields will not create a new `PaperTrail::Version`. In addition, these fields will not be included in the serialized version of the object whenever a new `PaperTrail::Version` is created.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ Undeleting is just as simple:
|
||||||
>> widget = Widget.find 42
|
>> widget = Widget.find 42
|
||||||
>> widget.destroy
|
>> widget.destroy
|
||||||
# Time passes....
|
# Time passes....
|
||||||
>> widget = Version.find(153).reify # the widget as it was before it was destroyed
|
>> widget = PaperTrail::Version.find(153).reify # the widget as it was before it was destroyed
|
||||||
>> widget.save # the widget lives!
|
>> widget.save # the widget lives!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ In a migration or in `rails console` you can set who is responsible like this:
|
||||||
You can avoid having to do this manually by setting your initializer to pick up the username of the current user from the OS, like this:
|
You can avoid having to do this manually by setting your initializer to pick up the username of the current user from the OS, like this:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
class Version < ActiveRecord::Base
|
class PaperTrail::Version < ActiveRecord::Base
|
||||||
if defined?(Rails::Console)
|
if defined?(Rails::Console)
|
||||||
PaperTrail.whodunnit = "#{`whoami`.strip}: console"
|
PaperTrail.whodunnit = "#{`whoami`.strip}: console"
|
||||||
elsif File.basename($0) == "rake"
|
elsif File.basename($0) == "rake"
|
||||||
|
@ -423,7 +423,7 @@ To find out who made a `version`'s object look that way, use `version.originator
|
||||||
You can specify custom version subclasses with the `:class_name` option:
|
You can specify custom version subclasses with the `:class_name` option:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
class PostVersion < Version
|
class PostVersion < PaperTrail::Version
|
||||||
# custom behaviour, e.g:
|
# custom behaviour, e.g:
|
||||||
self.table_name = :post_versions
|
self.table_name = :post_versions
|
||||||
end
|
end
|
||||||
|
@ -438,7 +438,7 @@ This allows you to store each model's versions in a separate table, which is use
|
||||||
If you are using Postgres, you should also define the sequence that your custom version class will use:
|
If you are using Postgres, you should also define the sequence that your custom version class will use:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
class PostVersion < Version
|
class PostVersion < PaperTrail::Version
|
||||||
self.table_name = :post_versions
|
self.table_name = :post_versions
|
||||||
self.sequence_name = :post_version_id_seq
|
self.sequence_name = :post_version_id_seq
|
||||||
end
|
end
|
||||||
|
@ -451,7 +451,7 @@ If you only use custom version classes and don't use PaperTrail's built-in one,
|
||||||
- either declare PaperTrail's version class abstract like this (in `config/initializers/paper_trail_patch.rb`):
|
- either declare PaperTrail's version class abstract like this (in `config/initializers/paper_trail_patch.rb`):
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Version.module_eval do
|
PaperTrail::Version.module_eval do
|
||||||
self.abstract_class = true
|
self.abstract_class = true
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
@ -609,15 +609,17 @@ For example:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# config/initializers/paper_trail.rb
|
# config/initializers/paper_trail.rb
|
||||||
class Version < ActiveRecord::Base
|
module PaperTrail
|
||||||
attr_accessible :author_id, :word_count, :answer
|
class Version < ActiveRecord::Base
|
||||||
|
attr_accessible :author_id, :word_count, :answer
|
||||||
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Why would you do this? In this example, `author_id` is an attribute of `Article` and PaperTrail will store it anyway in serialized (YAML) form in the `object` column of the `version` record. But let's say you wanted to pull out all versions for a particular author; without the metadata you would have to deserialize (reify) each `version` object to see if belonged to the author in question. Clearly this is inefficient. Using the metadata you can find just those versions you want:
|
Why would you do this? In this example, `author_id` is an attribute of `Article` and PaperTrail will store it anyway in serialized (YAML) form in the `object` column of the `version` record. But let's say you wanted to pull out all versions for a particular author; without the metadata you would have to deserialize (reify) each `version` object to see if belonged to the author in question. Clearly this is inefficient. Using the metadata you can find just those versions you want:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Version.all(:conditions => ['author_id = ?', author_id])
|
PaperTrail::Version.all(:conditions => ['author_id = ?', author_id])
|
||||||
```
|
```
|
||||||
|
|
||||||
Note you can pass a symbol as a value in the `meta` hash to signal a method to call.
|
Note you can pass a symbol as a value in the `meta` hash to signal a method to call.
|
||||||
|
@ -793,7 +795,7 @@ sql> delete from versions where created_at < 2010-06-01;
|
||||||
```
|
```
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
>> Version.delete_all ["created_at < ?", 1.week.ago]
|
>> PaperTrail::Version.delete_all ["created_at < ?", 1.week.ago]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
|
@ -39,7 +39,7 @@ module PaperTrail
|
||||||
attr_accessor self.version_association_name
|
attr_accessor self.version_association_name
|
||||||
|
|
||||||
class_attribute :version_class_name
|
class_attribute :version_class_name
|
||||||
self.version_class_name = options[:class_name] || '::Version'
|
self.version_class_name = options[:class_name] || 'PaperTrail::Version'
|
||||||
|
|
||||||
class_attribute :paper_trail_options
|
class_attribute :paper_trail_options
|
||||||
self.paper_trail_options = options.dup
|
self.paper_trail_options = options.dup
|
||||||
|
|
|
@ -1,198 +1,208 @@
|
||||||
class Version < ActiveRecord::Base
|
module PaperTrail
|
||||||
belongs_to :item, :polymorphic => true
|
class Version < ActiveRecord::Base
|
||||||
validates_presence_of :event
|
belongs_to :item, :polymorphic => true
|
||||||
attr_accessible :item_type, :item_id, :event, :whodunnit, :object, :object_changes
|
validates_presence_of :event
|
||||||
|
attr_accessible :item_type, :item_id, :event, :whodunnit, :object, :object_changes
|
||||||
|
|
||||||
after_create :enforce_version_limit!
|
after_create :enforce_version_limit!
|
||||||
|
|
||||||
def self.with_item_keys(item_type, item_id)
|
def self.with_item_keys(item_type, item_id)
|
||||||
where :item_type => item_type, :item_id => item_id
|
where :item_type => item_type, :item_id => item_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.creates
|
def self.creates
|
||||||
where :event => 'create'
|
where :event => 'create'
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.updates
|
def self.updates
|
||||||
where :event => 'update'
|
where :event => 'update'
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.destroys
|
def self.destroys
|
||||||
where :event => 'destroy'
|
where :event => 'destroy'
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.not_creates
|
def self.not_creates
|
||||||
where 'event <> ?', 'create'
|
where 'event <> ?', 'create'
|
||||||
end
|
end
|
||||||
|
|
||||||
scope :subsequent, lambda { |version|
|
scope :subsequent, lambda { |version|
|
||||||
where("#{self.primary_key} > ?", version).order("#{self.primary_key} ASC")
|
where("#{self.primary_key} > ?", version).order("#{self.primary_key} ASC")
|
||||||
}
|
}
|
||||||
|
|
||||||
scope :preceding, lambda { |version|
|
scope :preceding, lambda { |version|
|
||||||
where("#{self.primary_key} < ?", version).order("#{self.primary_key} DESC")
|
where("#{self.primary_key} < ?", version).order("#{self.primary_key} DESC")
|
||||||
}
|
}
|
||||||
|
|
||||||
scope :following, lambda { |timestamp|
|
scope :following, lambda { |timestamp|
|
||||||
# TODO: is this :order necessary, considering its presence on the has_many :versions association?
|
# TODO: is this :order necessary, considering its presence on the has_many :versions association?
|
||||||
where("#{PaperTrail.timestamp_field} > ?", timestamp).
|
where("#{PaperTrail.timestamp_field} > ?", timestamp).
|
||||||
order("#{PaperTrail.timestamp_field} ASC, #{self.primary_key} ASC")
|
order("#{PaperTrail.timestamp_field} ASC, #{self.primary_key} ASC")
|
||||||
}
|
}
|
||||||
|
|
||||||
scope :between, lambda { |start_time, end_time|
|
scope :between, lambda { |start_time, end_time|
|
||||||
where("#{PaperTrail.timestamp_field} > ? AND #{PaperTrail.timestamp_field} < ?", start_time, end_time).
|
where("#{PaperTrail.timestamp_field} > ? AND #{PaperTrail.timestamp_field} < ?", start_time, end_time).
|
||||||
order("#{PaperTrail.timestamp_field} ASC, #{self.primary_key} ASC")
|
order("#{PaperTrail.timestamp_field} ASC, #{self.primary_key} ASC")
|
||||||
}
|
}
|
||||||
|
|
||||||
# Restore the item from this version.
|
# Restore the item from this version.
|
||||||
#
|
#
|
||||||
# This will automatically restore all :has_one associations as they were "at the time",
|
# This will automatically restore all :has_one associations as they were "at the time",
|
||||||
# if they are also being versioned by PaperTrail. NOTE: this isn't always guaranteed
|
# if they are also being versioned by PaperTrail. NOTE: this isn't always guaranteed
|
||||||
# to work so you can either change the lookback period (from the default 3 seconds) or
|
# to work so you can either change the lookback period (from the default 3 seconds) or
|
||||||
# opt out.
|
# opt out.
|
||||||
#
|
#
|
||||||
# Options:
|
# Options:
|
||||||
# +:has_one+ set to `false` to opt out of has_one reification.
|
# +:has_one+ set to `false` to opt out of has_one reification.
|
||||||
# set to a float to change the lookback time (check whether your db supports
|
# set to a float to change the lookback time (check whether your db supports
|
||||||
# sub-second datetimes if you want them).
|
# sub-second datetimes if you want them).
|
||||||
def reify(options = {})
|
def reify(options = {})
|
||||||
without_identity_map do
|
without_identity_map do
|
||||||
options[:has_one] = 3 if options[:has_one] == true
|
options[:has_one] = 3 if options[:has_one] == true
|
||||||
options.reverse_merge! :has_one => false
|
options.reverse_merge! :has_one => false
|
||||||
|
|
||||||
unless object.nil?
|
unless object.nil?
|
||||||
attrs = PaperTrail.serializer.load object
|
attrs = PaperTrail.serializer.load object
|
||||||
|
|
||||||
# Normally a polymorphic belongs_to relationship allows us
|
# Normally a polymorphic belongs_to relationship allows us
|
||||||
# to get the object we belong to by calling, in this case,
|
# to get the object we belong to by calling, in this case,
|
||||||
# +item+. However this returns nil if +item+ has been
|
# +item+. However this returns nil if +item+ has been
|
||||||
# destroyed, and we need to be able to retrieve destroyed
|
# destroyed, and we need to be able to retrieve destroyed
|
||||||
# objects.
|
# objects.
|
||||||
#
|
#
|
||||||
# In this situation we constantize the +item_type+ to get hold of
|
# In this situation we constantize the +item_type+ to get hold of
|
||||||
# the class...except when the stored object's attributes
|
# the class...except when the stored object's attributes
|
||||||
# include a +type+ key. If this is the case, the object
|
# include a +type+ key. If this is the case, the object
|
||||||
# we belong to is using single table inheritance and the
|
# we belong to is using single table inheritance and the
|
||||||
# +item_type+ will be the base class, not the actual subclass.
|
# +item_type+ will be the base class, not the actual subclass.
|
||||||
# If +type+ is present but empty, the class is the base class.
|
# If +type+ is present but empty, the class is the base class.
|
||||||
|
|
||||||
if item
|
if item
|
||||||
model = item
|
model = item
|
||||||
# Look for attributes that exist in the model and not in this version. These attributes should be set to nil.
|
# Look for attributes that exist in the model and not in this version. These attributes should be set to nil.
|
||||||
(model.attribute_names - attrs.keys).each { |k| attrs[k] = nil }
|
(model.attribute_names - attrs.keys).each { |k| attrs[k] = nil }
|
||||||
else
|
|
||||||
inheritance_column_name = item_type.constantize.inheritance_column
|
|
||||||
class_name = attrs[inheritance_column_name].blank? ? item_type : attrs[inheritance_column_name]
|
|
||||||
klass = class_name.constantize
|
|
||||||
model = klass.new
|
|
||||||
end
|
|
||||||
|
|
||||||
model.class.unserialize_attributes_for_paper_trail attrs
|
|
||||||
|
|
||||||
# Set all the attributes in this version on the model
|
|
||||||
attrs.each do |k, v|
|
|
||||||
if model.respond_to?("#{k}=")
|
|
||||||
model[k.to_sym] = v
|
|
||||||
else
|
else
|
||||||
logger.warn "Attribute #{k} does not exist on #{item_type} (Version id: #{id})."
|
inheritance_column_name = item_type.constantize.inheritance_column
|
||||||
|
class_name = attrs[inheritance_column_name].blank? ? item_type : attrs[inheritance_column_name]
|
||||||
|
klass = class_name.constantize
|
||||||
|
model = klass.new
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
model.send "#{model.class.version_association_name}=", self
|
model.class.unserialize_attributes_for_paper_trail attrs
|
||||||
|
|
||||||
unless options[:has_one] == false
|
# Set all the attributes in this version on the model
|
||||||
reify_has_ones model, options[:has_one]
|
attrs.each do |k, v|
|
||||||
end
|
if model.respond_to?("#{k}=")
|
||||||
|
model[k.to_sym] = v
|
||||||
model
|
else
|
||||||
end
|
logger.warn "Attribute #{k} does not exist on #{item_type} (Version id: #{id})."
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# Returns what changed in this version of the item. Cf. `ActiveModel::Dirty#changes`.
|
|
||||||
# Returns nil if your `versions` table does not have an `object_changes` text column.
|
|
||||||
def changeset
|
|
||||||
return nil unless self.class.column_names.include? 'object_changes'
|
|
||||||
|
|
||||||
HashWithIndifferentAccess.new(PaperTrail.serializer.load(object_changes)).tap do |changes|
|
|
||||||
item_type.constantize.unserialize_attribute_changes(changes)
|
|
||||||
end
|
|
||||||
rescue
|
|
||||||
{}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns who put the item into the state stored in this version.
|
|
||||||
def originator
|
|
||||||
previous.try :whodunnit
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns who changed the item from the state it had in this version.
|
|
||||||
# This is an alias for `whodunnit`.
|
|
||||||
def terminator
|
|
||||||
whodunnit
|
|
||||||
end
|
|
||||||
|
|
||||||
def sibling_versions
|
|
||||||
self.class.with_item_keys(item_type, item_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next
|
|
||||||
sibling_versions.subsequent(self).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def previous
|
|
||||||
sibling_versions.preceding(self).first
|
|
||||||
end
|
|
||||||
|
|
||||||
def index
|
|
||||||
id_column = self.class.primary_key.to_sym
|
|
||||||
sibling_versions.select(id_column).order("#{id_column} ASC").map(&id_column).index(self.send(id_column))
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# In Rails 3.1+, calling reify on a previous version confuses the
|
|
||||||
# IdentityMap, if enabled. This prevents insertion into the map.
|
|
||||||
def without_identity_map(&block)
|
|
||||||
if defined?(ActiveRecord::IdentityMap) && ActiveRecord::IdentityMap.respond_to?(:without)
|
|
||||||
ActiveRecord::IdentityMap.without(&block)
|
|
||||||
else
|
|
||||||
block.call
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Restore the `model`'s has_one associations as they were when this version was
|
|
||||||
# superseded by the next (because that's what the user was looking at when they
|
|
||||||
# made the change).
|
|
||||||
#
|
|
||||||
# The `lookback` sets how many seconds before the model's change we go.
|
|
||||||
def reify_has_ones(model, lookback)
|
|
||||||
model.class.reflect_on_all_associations(:has_one).each do |assoc|
|
|
||||||
child = model.send assoc.name
|
|
||||||
if child.respond_to? :version_at
|
|
||||||
# N.B. we use version of the child as it was `lookback` seconds before the parent was updated.
|
|
||||||
# Ideally we want the version of the child as it was just before the parent was updated...
|
|
||||||
# but until PaperTrail knows which updates are "together" (e.g. parent and child being
|
|
||||||
# updated on the same form), it's impossible to tell when the overall update started;
|
|
||||||
# and therefore impossible to know when "just before" was.
|
|
||||||
if (child_as_it_was = child.version_at(send(PaperTrail.timestamp_field) - lookback.seconds))
|
|
||||||
child_as_it_was.attributes.each do |k,v|
|
|
||||||
model.send(assoc.name).send :write_attribute, k.to_sym, v rescue nil
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
model.send "#{assoc.name}=", nil
|
model.send "#{model.class.version_association_name}=", self
|
||||||
|
|
||||||
|
unless options[:has_one] == false
|
||||||
|
reify_has_ones model, options[:has_one]
|
||||||
|
end
|
||||||
|
|
||||||
|
model
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# checks to see if a value has been set for the `version_limit` config option, and if so enforces it
|
# Returns what changed in this version of the item. Cf. `ActiveModel::Dirty#changes`.
|
||||||
def enforce_version_limit!
|
# Returns nil if your `versions` table does not have an `object_changes` text column.
|
||||||
return unless PaperTrail.config.version_limit.is_a? Numeric
|
def changeset
|
||||||
previous_versions = sibling_versions.not_creates
|
return nil unless self.class.column_names.include? 'object_changes'
|
||||||
return unless previous_versions.size > PaperTrail.config.version_limit
|
|
||||||
excess_previous_versions = previous_versions - previous_versions.last(PaperTrail.config.version_limit)
|
|
||||||
excess_previous_versions.map(&:destroy)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
HashWithIndifferentAccess.new(PaperTrail.serializer.load(object_changes)).tap do |changes|
|
||||||
|
item_type.constantize.unserialize_attribute_changes(changes)
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
{}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns who put the item into the state stored in this version.
|
||||||
|
def originator
|
||||||
|
previous.try :whodunnit
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns who changed the item from the state it had in this version.
|
||||||
|
# This is an alias for `whodunnit`.
|
||||||
|
def terminator
|
||||||
|
whodunnit
|
||||||
|
end
|
||||||
|
|
||||||
|
def sibling_versions
|
||||||
|
self.class.with_item_keys(item_type, item_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next
|
||||||
|
sibling_versions.subsequent(self).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def previous
|
||||||
|
sibling_versions.preceding(self).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def index
|
||||||
|
id_column = self.class.primary_key.to_sym
|
||||||
|
sibling_versions.select(id_column).order("#{id_column} ASC").map(&id_column).index(self.send(id_column))
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# In Rails 3.1+, calling reify on a previous version confuses the
|
||||||
|
# IdentityMap, if enabled. This prevents insertion into the map.
|
||||||
|
def without_identity_map(&block)
|
||||||
|
if defined?(ActiveRecord::IdentityMap) && ActiveRecord::IdentityMap.respond_to?(:without)
|
||||||
|
ActiveRecord::IdentityMap.without(&block)
|
||||||
|
else
|
||||||
|
block.call
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Restore the `model`'s has_one associations as they were when this version was
|
||||||
|
# superseded by the next (because that's what the user was looking at when they
|
||||||
|
# made the change).
|
||||||
|
#
|
||||||
|
# The `lookback` sets how many seconds before the model's change we go.
|
||||||
|
def reify_has_ones(model, lookback)
|
||||||
|
model.class.reflect_on_all_associations(:has_one).each do |assoc|
|
||||||
|
child = model.send assoc.name
|
||||||
|
if child.respond_to? :version_at
|
||||||
|
# N.B. we use version of the child as it was `lookback` seconds before the parent was updated.
|
||||||
|
# Ideally we want the version of the child as it was just before the parent was updated...
|
||||||
|
# but until PaperTrail knows which updates are "together" (e.g. parent and child being
|
||||||
|
# updated on the same form), it's impossible to tell when the overall update started;
|
||||||
|
# and therefore impossible to know when "just before" was.
|
||||||
|
if (child_as_it_was = child.version_at(send(PaperTrail.timestamp_field) - lookback.seconds))
|
||||||
|
child_as_it_was.attributes.each do |k,v|
|
||||||
|
model.send(assoc.name).send :write_attribute, k.to_sym, v rescue nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
model.send "#{assoc.name}=", nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# checks to see if a value has been set for the `version_limit` config option, and if so enforces it
|
||||||
|
def enforce_version_limit!
|
||||||
|
return unless PaperTrail.config.version_limit.is_a? Numeric
|
||||||
|
previous_versions = sibling_versions.not_creates
|
||||||
|
return unless previous_versions.size > PaperTrail.config.version_limit
|
||||||
|
excess_previous_versions = previous_versions - previous_versions.last(PaperTrail.config.version_limit)
|
||||||
|
excess_previous_versions.map(&:destroy)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Legacy support for old applications using the original `Version` class
|
||||||
|
# class Version < PaperTrail::Version
|
||||||
|
# def initialize
|
||||||
|
# warn "DEPRECATED: Please use the namespaced `PaperTrail::Version` class instead."
|
||||||
|
# super
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
class PostVersion < Version
|
class PostVersion < PaperTrail::Version
|
||||||
self.table_name = 'post_versions'
|
self.table_name = 'post_versions'
|
||||||
end
|
end
|
|
@ -1,3 +1,5 @@
|
||||||
class Version < ActiveRecord::Base
|
module PaperTrail
|
||||||
attr_accessible :created_at, :updated_at, :answer, :action, :question, :article_id, :ip, :user_agent, :title
|
class Version < ActiveRecord::Base
|
||||||
|
attr_accessible :created_at, :updated_at, :answer, :action, :question, :article_id, :ip, :user_agent, :title
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,7 @@ class ControllerTest < ActionController::TestCase
|
||||||
assert_equal 0, w.versions.length
|
assert_equal 0, w.versions.length
|
||||||
delete :destroy, :id => w.id
|
delete :destroy, :id => w.id
|
||||||
widget = assigns(:widget)
|
widget = assigns(:widget)
|
||||||
assert_equal 0, Version.with_item_keys('Widget', w.id).size
|
assert_equal 0, PaperTrail::Version.with_item_keys('Widget', w.id).size
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'create' do
|
test 'create' do
|
||||||
|
@ -62,7 +62,7 @@ class ControllerTest < ActionController::TestCase
|
||||||
assert_equal 1, w.versions.length
|
assert_equal 1, w.versions.length
|
||||||
delete :destroy, :id => w.id
|
delete :destroy, :id => w.id
|
||||||
widget = assigns(:widget)
|
widget = assigns(:widget)
|
||||||
versions_for_widget = Version.with_item_keys('Widget', w.id)
|
versions_for_widget = PaperTrail::Version.with_item_keys('Widget', w.id)
|
||||||
assert_equal 2, versions_for_widget.length
|
assert_equal 2, versions_for_widget.length
|
||||||
assert_equal 153, versions_for_widget.last.whodunnit.to_i
|
assert_equal 153, versions_for_widget.last.whodunnit.to_i
|
||||||
assert_equal '127.0.0.1', versions_for_widget.last.ip
|
assert_equal '127.0.0.1', versions_for_widget.last.ip
|
||||||
|
|
|
@ -2,7 +2,7 @@ require 'test_helper'
|
||||||
|
|
||||||
class PaperTrailTest < ActiveSupport::TestCase
|
class PaperTrailTest < ActiveSupport::TestCase
|
||||||
test 'Sanity test' do
|
test 'Sanity test' do
|
||||||
assert_kind_of Module, PaperTrail
|
assert_kind_of Module, PaperTrail::Version
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'create with plain model class' do
|
test 'create with plain model class' do
|
||||||
|
@ -21,7 +21,7 @@ class PaperTrailTest < ActiveSupport::TestCase
|
||||||
widget = Widget.create
|
widget = Widget.create
|
||||||
assert_equal 1, widget.versions.length
|
assert_equal 1, widget.versions.length
|
||||||
widget.destroy
|
widget.destroy
|
||||||
versions_for_widget = Version.with_item_keys('Widget', widget.id)
|
versions_for_widget = PaperTrail::Version.with_item_keys('Widget', widget.id)
|
||||||
assert_equal 2, versions_for_widget.length
|
assert_equal 2, versions_for_widget.length
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,19 +21,19 @@ class InheritanceColumnTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'work with custom STI inheritance column' do
|
should 'work with custom STI inheritance column' do
|
||||||
assert_equal 12, Version.count
|
assert_equal 12, PaperTrail::Version.count
|
||||||
assert_equal 4, @animal.versions.count
|
assert_equal 4, @animal.versions.count
|
||||||
assert @animal.versions.first.reify.nil?
|
assert @animal.versions.first.reify.nil?
|
||||||
@animal.versions[1..-1].each { |v| assert_equal 'Animal', v.reify.class.name }
|
@animal.versions[1..-1].each { |v| assert_equal 'Animal', v.reify.class.name }
|
||||||
|
|
||||||
# For some reason `@dog.versions` doesn't include the final `destroy` version.
|
# For some reason `@dog.versions` doesn't include the final `destroy` version.
|
||||||
# Neither do `@dog.versions.scoped` nor `@dog.versions(true)` nor `@dog.versions.reload`.
|
# Neither do `@dog.versions.scoped` nor `@dog.versions(true)` nor `@dog.versions.reload`.
|
||||||
dog_versions = Version.where(:item_id => @dog.id)
|
dog_versions = PaperTrail::Version.where(:item_id => @dog.id)
|
||||||
assert_equal 4, dog_versions.count
|
assert_equal 4, dog_versions.count
|
||||||
assert dog_versions.first.reify.nil?
|
assert dog_versions.first.reify.nil?
|
||||||
dog_versions[1..-1].each { |v| assert_equal 'Dog', v.reify.class.name }
|
dog_versions[1..-1].each { |v| assert_equal 'Dog', v.reify.class.name }
|
||||||
|
|
||||||
cat_versions = Version.where(:item_id => @cat.id)
|
cat_versions = PaperTrail::Version.where(:item_id => @cat.id)
|
||||||
assert_equal 4, cat_versions.count
|
assert_equal 4, cat_versions.count
|
||||||
assert cat_versions.first.reify.nil?
|
assert cat_versions.first.reify.nil?
|
||||||
cat_versions[1..-1].each { |v| assert_equal 'Cat', v.reify.class.name }
|
cat_versions[1..-1].each { |v| assert_equal 'Cat', v.reify.class.name }
|
||||||
|
|
|
@ -4,16 +4,16 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'A record with defined "only" and "ignore" attributes' do
|
context 'A record with defined "only" and "ignore" attributes' do
|
||||||
setup { @article = Article.create }
|
setup { @article = Article.create }
|
||||||
should 'creation should change the number of versions' do assert_equal(1, Version.count) end
|
should 'creation should change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
||||||
|
|
||||||
context 'which updates an ignored column' do
|
context 'which updates an ignored column' do
|
||||||
setup { @article.update_attributes :title => 'My first title' }
|
setup { @article.update_attributes :title => 'My first title' }
|
||||||
should 'not change the number of versions' do assert_equal(1, Version.count) end
|
should 'not change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'which updates an ignored column and a selected column' do
|
context 'which updates an ignored column and a selected column' do
|
||||||
setup { @article.update_attributes :title => 'My first title', :content => 'Some text here.' }
|
setup { @article.update_attributes :title => 'My first title', :content => 'Some text here.' }
|
||||||
should 'change the number of versions' do assert_equal(2, Version.count) end
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
||||||
|
|
||||||
should "show the new version in the model's `versions` association" do
|
should "show the new version in the model's `versions` association" do
|
||||||
assert_equal(2, @article.versions.size)
|
assert_equal(2, @article.versions.size)
|
||||||
|
@ -26,7 +26,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'which updates a selected column' do
|
context 'which updates a selected column' do
|
||||||
setup { @article.update_attributes :content => 'Some text here.' }
|
setup { @article.update_attributes :content => 'Some text here.' }
|
||||||
should 'change the number of versions' do assert_equal(2, Version.count) end
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
||||||
|
|
||||||
should "show the new version in the model's `versions` association" do
|
should "show the new version in the model's `versions` association" do
|
||||||
assert_equal(2, @article.versions.size)
|
assert_equal(2, @article.versions.size)
|
||||||
|
@ -35,17 +35,17 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'which updates a non-ignored and non-selected column' do
|
context 'which updates a non-ignored and non-selected column' do
|
||||||
setup { @article.update_attributes :abstract => 'Other abstract'}
|
setup { @article.update_attributes :abstract => 'Other abstract'}
|
||||||
should 'not change the number of versions' do assert_equal(1, Version.count) end
|
should 'not change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'which updates a skipped column' do
|
context 'which updates a skipped column' do
|
||||||
setup { @article.update_attributes :file_upload => 'Your data goes here' }
|
setup { @article.update_attributes :file_upload => 'Your data goes here' }
|
||||||
should 'not change the number of versions' do assert_equal(1, Version.count) end
|
should 'not change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'which updates a skipped column and a selected column' do
|
context 'which updates a skipped column and a selected column' do
|
||||||
setup { @article.update_attributes :file_upload => 'Your data goes here', :content => 'Some text here.' }
|
setup { @article.update_attributes :file_upload => 'Your data goes here', :content => 'Some text here.' }
|
||||||
should 'change the number of versions' do assert_equal(2, Version.count) end
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
||||||
|
|
||||||
should "show the new version in the model's `versions` association" do
|
should "show the new version in the model's `versions` association" do
|
||||||
assert_equal(2, @article.versions.size)
|
assert_equal(2, @article.versions.size)
|
||||||
|
@ -73,7 +73,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'which gets destroyed' do
|
context 'which gets destroyed' do
|
||||||
setup { @article.destroy }
|
setup { @article.destroy }
|
||||||
should 'change the number of versions' do assert_equal(2, Version.count) end
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
||||||
|
|
||||||
should "show the new version in the model's `versions` association" do
|
should "show the new version in the model's `versions` association" do
|
||||||
assert_equal(2, @article.versions.size)
|
assert_equal(2, @article.versions.size)
|
||||||
|
@ -86,7 +86,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'which updates an ignored column' do
|
context 'which updates an ignored column' do
|
||||||
setup { @legacy_widget.update_attributes :version => 1 }
|
setup { @legacy_widget.update_attributes :version => 1 }
|
||||||
should 'not change the number of versions' do assert_equal(1, Version.count) end
|
should 'not change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -95,16 +95,16 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'for non-US translations' do
|
context 'for non-US translations' do
|
||||||
setup { @translation.save }
|
setup { @translation.save }
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
|
|
||||||
context 'after update' do
|
context 'after update' do
|
||||||
setup { @translation.update_attributes :content => 'Content' }
|
setup { @translation.update_attributes :content => 'Content' }
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'after destroy' do
|
context 'after destroy' do
|
||||||
setup { @translation.destroy }
|
setup { @translation.destroy }
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -117,22 +117,22 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
@translation.save
|
@translation.save
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
|
|
||||||
context 'after update' do
|
context 'after update' do
|
||||||
setup { @translation.update_attributes :content => 'Content' }
|
setup { @translation.update_attributes :content => 'Content' }
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'that are not drafts' do
|
context 'that are not drafts' do
|
||||||
setup { @translation.save }
|
setup { @translation.save }
|
||||||
|
|
||||||
should 'change the number of versions' do assert_equal(1, Version.count) end
|
should 'change the number of versions' do assert_equal(1, PaperTrail::Version.count) end
|
||||||
|
|
||||||
context 'after update' do
|
context 'after update' do
|
||||||
setup { @translation.update_attributes :content => 'Content' }
|
setup { @translation.update_attributes :content => 'Content' }
|
||||||
should 'change the number of versions' do assert_equal(2, Version.count) end
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
||||||
|
|
||||||
should "show the new version in the model's `versions` association" do
|
should "show the new version in the model's `versions` association" do
|
||||||
assert_equal(2, @translation.versions.size)
|
assert_equal(2, @translation.versions.size)
|
||||||
|
@ -141,7 +141,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
context 'after destroy' do
|
context 'after destroy' do
|
||||||
setup { @translation.destroy }
|
setup { @translation.destroy }
|
||||||
should 'change the number of versions' do assert_equal(2, Version.count) end
|
should 'change the number of versions' do assert_equal(2, PaperTrail::Version.count) end
|
||||||
|
|
||||||
should "show the new version in the model's `versions` association" do
|
should "show the new version in the model's `versions` association" do
|
||||||
assert_equal(2, @translation.versions.size)
|
assert_equal(2, @translation.versions.size)
|
||||||
|
@ -297,15 +297,15 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
setup do
|
setup do
|
||||||
@fluxor = @widget.fluxors.create :name => 'flux'
|
@fluxor = @widget.fluxors.create :name => 'flux'
|
||||||
@widget.destroy
|
@widget.destroy
|
||||||
@reified_widget = Version.last.reify
|
@reified_widget = PaperTrail::Version.last.reify
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'record the correct event' do
|
should 'record the correct event' do
|
||||||
assert_match /destroy/i, Version.last.event
|
assert_match /destroy/i, PaperTrail::Version.last.event
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'have three previous versions' do
|
should 'have three previous versions' do
|
||||||
assert_equal 3, Version.with_item_keys('Widget', @widget.id).length
|
assert_equal 3, PaperTrail::Version.with_item_keys('Widget', @widget.id).length
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'be available in its previous version' do
|
should 'be available in its previous version' do
|
||||||
|
@ -536,7 +536,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
setup do
|
setup do
|
||||||
PaperTrail.whodunnit = 'Charlie'
|
PaperTrail.whodunnit = 'Charlie'
|
||||||
@widget.destroy
|
@widget.destroy
|
||||||
@version = Version.last
|
@version = PaperTrail::Version.last
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'track who made the change' do
|
should 'track who made the change' do
|
||||||
|
@ -558,10 +558,10 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'reify with the correct type' do
|
should 'reify with the correct type' do
|
||||||
thing = Version.last.reify
|
thing = PaperTrail::Version.last.reify
|
||||||
assert_kind_of FooWidget, thing
|
assert_kind_of FooWidget, thing
|
||||||
assert_equal @foo.versions.first, Version.last.previous
|
assert_equal @foo.versions.first, PaperTrail::Version.last.previous
|
||||||
assert_nil Version.last.next
|
assert_nil PaperTrail::Version.last.next
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'should return the correct originator' do
|
should 'should return the correct originator' do
|
||||||
|
@ -574,10 +574,10 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
setup { @foo.destroy }
|
setup { @foo.destroy }
|
||||||
|
|
||||||
should 'reify with the correct type' do
|
should 'reify with the correct type' do
|
||||||
thing = Version.last.reify
|
thing = PaperTrail::Version.last.reify
|
||||||
assert_kind_of FooWidget, thing
|
assert_kind_of FooWidget, thing
|
||||||
assert_equal @foo.versions[1], Version.last.previous
|
assert_equal @foo.versions[1], PaperTrail::Version.last.previous
|
||||||
assert_nil Version.last.next
|
assert_nil PaperTrail::Version.last.next
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -840,35 +840,35 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'store version on source <<' do
|
should 'store version on source <<' do
|
||||||
count = Version.count
|
count = PaperTrail::Version.count
|
||||||
@book.authors << @dostoyevsky
|
@book.authors << @dostoyevsky
|
||||||
assert_equal 1, Version.count - count
|
assert_equal 1, PaperTrail::Version.count - count
|
||||||
assert_equal Version.last, @book.authorships.first.versions.first
|
assert_equal PaperTrail::Version.last, @book.authorships.first.versions.first
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'store version on source create' do
|
should 'store version on source create' do
|
||||||
count = Version.count
|
count = PaperTrail::Version.count
|
||||||
@book.authors.create :name => 'Tolstoy'
|
@book.authors.create :name => 'Tolstoy'
|
||||||
assert_equal 2, Version.count - count
|
assert_equal 2, PaperTrail::Version.count - count
|
||||||
assert_same_elements [Person.last, Authorship.last], [Version.all[-2].item, Version.last.item]
|
assert_same_elements [Person.last, Authorship.last], [PaperTrail::Version.all[-2].item, PaperTrail::Version.last.item]
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'store version on join destroy' do
|
should 'store version on join destroy' do
|
||||||
@book.authors << @dostoyevsky
|
@book.authors << @dostoyevsky
|
||||||
count = Version.count
|
count = PaperTrail::Version.count
|
||||||
@book.authorships(true).last.destroy
|
@book.authorships(true).last.destroy
|
||||||
assert_equal 1, Version.count - count
|
assert_equal 1, PaperTrail::Version.count - count
|
||||||
assert_equal @book, Version.last.reify.book
|
assert_equal @book, PaperTrail::Version.last.reify.book
|
||||||
assert_equal @dostoyevsky, Version.last.reify.person
|
assert_equal @dostoyevsky, PaperTrail::Version.last.reify.person
|
||||||
end
|
end
|
||||||
|
|
||||||
should 'store version on join clear' do
|
should 'store version on join clear' do
|
||||||
@book.authors << @dostoyevsky
|
@book.authors << @dostoyevsky
|
||||||
count = Version.count
|
count = PaperTrail::Version.count
|
||||||
@book.authorships(true).clear
|
@book.authorships(true).clear
|
||||||
assert_equal 1, Version.count - count
|
assert_equal 1, PaperTrail::Version.count - count
|
||||||
assert_equal @book, Version.last.reify.book
|
assert_equal @book, PaperTrail::Version.last.reify.book
|
||||||
assert_equal @dostoyevsky, Version.last.reify.person
|
assert_equal @dostoyevsky, PaperTrail::Version.last.reify.person
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1038,17 +1038,17 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
context 'A new model instance which uses a custom Version class' do
|
context 'A new model instance which uses a custom PaperTrail::Version class' do
|
||||||
setup { @post = Post.new }
|
setup { @post = Post.new }
|
||||||
|
|
||||||
context 'which is then saved' do
|
context 'which is then saved' do
|
||||||
setup { @post.save }
|
setup { @post.save }
|
||||||
should 'change the number of post versions' do assert_equal 1, PostVersion.count end
|
should 'change the number of post versions' do assert_equal 1, PostVersion.count end
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'An existing model instance which uses a custom Version class' do
|
context 'An existing model instance which uses a custom PaperTrail::Version class' do
|
||||||
setup { @post = Post.create }
|
setup { @post = Post.create }
|
||||||
should 'have one post version' do assert_equal(1, PostVersion.count) end
|
should 'have one post version' do assert_equal(1, PostVersion.count) end
|
||||||
|
|
||||||
|
@ -1067,7 +1067,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
context 'which is modified' do
|
context 'which is modified' do
|
||||||
setup { @post.update_attributes({ :content => "Some new content" }) }
|
setup { @post.update_attributes({ :content => "Some new content" }) }
|
||||||
should 'change the number of post versions' do assert_equal(2, PostVersion.count) end
|
should 'change the number of post versions' do assert_equal(2, PostVersion.count) end
|
||||||
should 'not change the number of versions' do assert_equal(0, Version.count) end
|
should 'not change the number of versions' do assert_equal(0, PaperTrail::Version.count) end
|
||||||
should "not have stored changes when object_changes column doesn't exist" do
|
should "not have stored changes when object_changes column doesn't exist" do
|
||||||
assert_nil @post.versions.last.changeset
|
assert_nil @post.versions.last.changeset
|
||||||
end
|
end
|
||||||
|
@ -1287,9 +1287,9 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
||||||
# Updates `model`'s last version so it looks like the version was
|
# Updates `model`'s last version so it looks like the version was
|
||||||
# created 2 seconds ago.
|
# created 2 seconds ago.
|
||||||
def make_last_version_earlier(model)
|
def make_last_version_earlier(model)
|
||||||
Version.record_timestamps = false
|
PaperTrail::Version.record_timestamps = false
|
||||||
model.versions.last.update_attributes :created_at => 2.seconds.ago
|
model.versions.last.update_attributes :created_at => 2.seconds.ago
|
||||||
Version.record_timestamps = true
|
PaperTrail::Version.record_timestamps = true
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,8 +5,8 @@ class TimestampTest < ActiveSupport::TestCase
|
||||||
setup do
|
setup do
|
||||||
PaperTrail.timestamp_field = :custom_created_at
|
PaperTrail.timestamp_field = :custom_created_at
|
||||||
change_schema
|
change_schema
|
||||||
Version.connection.schema_cache.clear!
|
PaperTrail::Version.connection.schema_cache.clear!
|
||||||
Version.reset_column_information
|
PaperTrail::Version.reset_column_information
|
||||||
|
|
||||||
Fluxor.instance_eval <<-END
|
Fluxor.instance_eval <<-END
|
||||||
has_paper_trail
|
has_paper_trail
|
||||||
|
|
|
@ -1,55 +1,55 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class VersionTest < ActiveSupport::TestCase
|
class PaperTrail::VersionTest < ActiveSupport::TestCase
|
||||||
setup {
|
setup {
|
||||||
change_schema
|
change_schema
|
||||||
@article = Animal.create
|
@article = Animal.create
|
||||||
assert Version.creates.present?
|
assert PaperTrail::Version.creates.present?
|
||||||
}
|
}
|
||||||
|
|
||||||
context "Version.creates" do
|
context "PaperTrail::Version.creates" do
|
||||||
should "return only create events" do
|
should "return only create events" do
|
||||||
Version.creates.each do |version|
|
PaperTrail::Version.creates.each do |version|
|
||||||
assert_equal "create", version.event
|
assert_equal "create", version.event
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Version.updates" do
|
context "PaperTrail::Version.updates" do
|
||||||
setup {
|
setup {
|
||||||
@article.update_attributes(:name => 'Animal')
|
@article.update_attributes(:name => 'Animal')
|
||||||
assert Version.updates.present?
|
assert PaperTrail::Version.updates.present?
|
||||||
}
|
}
|
||||||
|
|
||||||
should "return only update events" do
|
should "return only update events" do
|
||||||
Version.updates.each do |version|
|
PaperTrail::Version.updates.each do |version|
|
||||||
assert_equal "update", version.event
|
assert_equal "update", version.event
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Version.destroys" do
|
context "PaperTrail::Version.destroys" do
|
||||||
setup {
|
setup {
|
||||||
@article.destroy
|
@article.destroy
|
||||||
assert Version.destroys.present?
|
assert PaperTrail::Version.destroys.present?
|
||||||
}
|
}
|
||||||
|
|
||||||
should "return only destroy events" do
|
should "return only destroy events" do
|
||||||
Version.destroys.each do |version|
|
PaperTrail::Version.destroys.each do |version|
|
||||||
assert_equal "destroy", version.event
|
assert_equal "destroy", version.event
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "Version.not_creates" do
|
context "PaperTrail::Version.not_creates" do
|
||||||
setup {
|
setup {
|
||||||
@article.update_attributes(:name => 'Animal')
|
@article.update_attributes(:name => 'Animal')
|
||||||
@article.destroy
|
@article.destroy
|
||||||
assert Version.not_creates.present?
|
assert PaperTrail::Version.not_creates.present?
|
||||||
}
|
}
|
||||||
|
|
||||||
should "return all items except create events" do
|
should "return all items except create events" do
|
||||||
Version.not_creates.each do |version|
|
PaperTrail::Version.not_creates.each do |version|
|
||||||
assert_not_equal "create", version.event
|
assert_not_equal "create", version.event
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue