diff --git a/README.md b/README.md index f652a424..335c3588 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Widget.paper_trail_off Widget.paper_trail_on ``` -And a `Version` instance has these methods: +And a `PaperTrail::Version` instance has these methods: ```ruby # 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 >> widget = Widget.find 42 ->> widget.versions # [, , ...] +>> widget.versions # [, , ...] ``` Once you have a version, you can find out what happened: @@ -193,7 +193,7 @@ class Article < ActiveRecord::Base 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 falling back on one of the default events. @@ -233,7 +233,7 @@ class Article < ActiveRecord::Base 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 >> 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`. -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: @@ -304,7 +304,7 @@ Undeleting is just as simple: >> widget = Widget.find 42 >> widget.destroy # 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! ``` @@ -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: ```ruby -class Version < ActiveRecord::Base +class PaperTrail::Version < ActiveRecord::Base if defined?(Rails::Console) PaperTrail.whodunnit = "#{`whoami`.strip}: console" 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: ```ruby -class PostVersion < Version +class PostVersion < PaperTrail::Version # custom behaviour, e.g: self.table_name = :post_versions 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: ```ruby -class PostVersion < Version +class PostVersion < PaperTrail::Version self.table_name = :post_versions self.sequence_name = :post_version_id_seq 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`): ```ruby -Version.module_eval do +PaperTrail::Version.module_eval do self.abstract_class = true end ``` @@ -609,15 +609,17 @@ For example: ```ruby # config/initializers/paper_trail.rb -class Version < ActiveRecord::Base - attr_accessible :author_id, :word_count, :answer +module PaperTrail + class Version < ActiveRecord::Base + attr_accessible :author_id, :word_count, :answer + 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: ```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. @@ -793,7 +795,7 @@ sql> delete from versions where created_at < 2010-06-01; ``` ```ruby ->> Version.delete_all ["created_at < ?", 1.week.ago] +>> PaperTrail::Version.delete_all ["created_at < ?", 1.week.ago] ``` ## Installation diff --git a/lib/paper_trail/has_paper_trail.rb b/lib/paper_trail/has_paper_trail.rb index 3201736f..800439cd 100644 --- a/lib/paper_trail/has_paper_trail.rb +++ b/lib/paper_trail/has_paper_trail.rb @@ -39,7 +39,7 @@ module PaperTrail attr_accessor self.version_association_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 self.paper_trail_options = options.dup diff --git a/lib/paper_trail/version.rb b/lib/paper_trail/version.rb index ac81ffc7..d55bd611 100644 --- a/lib/paper_trail/version.rb +++ b/lib/paper_trail/version.rb @@ -1,198 +1,208 @@ -class Version < ActiveRecord::Base - belongs_to :item, :polymorphic => true - validates_presence_of :event - attr_accessible :item_type, :item_id, :event, :whodunnit, :object, :object_changes +module PaperTrail + class Version < ActiveRecord::Base + belongs_to :item, :polymorphic => true + 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) - where :item_type => item_type, :item_id => item_id - end + def self.with_item_keys(item_type, item_id) + where :item_type => item_type, :item_id => item_id + end - def self.creates - where :event => 'create' - end + def self.creates + where :event => 'create' + end - def self.updates - where :event => 'update' - end + def self.updates + where :event => 'update' + end - def self.destroys - where :event => 'destroy' - end + def self.destroys + where :event => 'destroy' + end - def self.not_creates - where 'event <> ?', 'create' - end + def self.not_creates + where 'event <> ?', 'create' + end - scope :subsequent, lambda { |version| - where("#{self.primary_key} > ?", version).order("#{self.primary_key} ASC") - } + scope :subsequent, lambda { |version| + where("#{self.primary_key} > ?", version).order("#{self.primary_key} ASC") + } - scope :preceding, lambda { |version| - where("#{self.primary_key} < ?", version).order("#{self.primary_key} DESC") - } + scope :preceding, lambda { |version| + where("#{self.primary_key} < ?", version).order("#{self.primary_key} DESC") + } - scope :following, lambda { |timestamp| - # TODO: is this :order necessary, considering its presence on the has_many :versions association? - where("#{PaperTrail.timestamp_field} > ?", timestamp). - order("#{PaperTrail.timestamp_field} ASC, #{self.primary_key} ASC") - } + scope :following, lambda { |timestamp| + # TODO: is this :order necessary, considering its presence on the has_many :versions association? + where("#{PaperTrail.timestamp_field} > ?", timestamp). + order("#{PaperTrail.timestamp_field} ASC, #{self.primary_key} ASC") + } - scope :between, lambda { |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") - } + scope :between, lambda { |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") + } - # Restore the item from this version. - # - # 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 - # to work so you can either change the lookback period (from the default 3 seconds) or - # opt out. - # - # Options: - # +: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 - # sub-second datetimes if you want them). - def reify(options = {}) - without_identity_map do - options[:has_one] = 3 if options[:has_one] == true - options.reverse_merge! :has_one => false + # Restore the item from this version. + # + # 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 + # to work so you can either change the lookback period (from the default 3 seconds) or + # opt out. + # + # Options: + # +: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 + # sub-second datetimes if you want them). + def reify(options = {}) + without_identity_map do + options[:has_one] = 3 if options[:has_one] == true + options.reverse_merge! :has_one => false - unless object.nil? - attrs = PaperTrail.serializer.load object + unless object.nil? + attrs = PaperTrail.serializer.load object - # Normally a polymorphic belongs_to relationship allows us - # to get the object we belong to by calling, in this case, - # +item+. However this returns nil if +item+ has been - # destroyed, and we need to be able to retrieve destroyed - # objects. - # - # In this situation we constantize the +item_type+ to get hold of - # the class...except when the stored object's attributes - # include a +type+ key. If this is the case, the object - # we belong to is using single table inheritance and the - # +item_type+ will be the base class, not the actual subclass. - # If +type+ is present but empty, the class is the base class. + # Normally a polymorphic belongs_to relationship allows us + # to get the object we belong to by calling, in this case, + # +item+. However this returns nil if +item+ has been + # destroyed, and we need to be able to retrieve destroyed + # objects. + # + # In this situation we constantize the +item_type+ to get hold of + # the class...except when the stored object's attributes + # include a +type+ key. If this is the case, the object + # we belong to is using single table inheritance and the + # +item_type+ will be the base class, not the actual subclass. + # If +type+ is present but empty, the class is the base class. - if item - model = item - # 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 } - 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 + if item + model = item + # 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 } 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 - model.send "#{model.class.version_association_name}=", self + model.class.unserialize_attributes_for_paper_trail attrs - unless options[:has_one] == false - reify_has_ones model, options[:has_one] - end - - model - 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 + # 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 + logger.warn "Attribute #{k} does not exist on #{item_type} (Version id: #{id})." + 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 - # 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 + # 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 + 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 + +# 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 diff --git a/test/dummy/app/versions/post_version.rb b/test/dummy/app/versions/post_version.rb index f1bb11e2..c8fe5dbe 100644 --- a/test/dummy/app/versions/post_version.rb +++ b/test/dummy/app/versions/post_version.rb @@ -1,3 +1,3 @@ -class PostVersion < Version +class PostVersion < PaperTrail::Version self.table_name = 'post_versions' end \ No newline at end of file diff --git a/test/dummy/config/initializers/paper_trail.rb b/test/dummy/config/initializers/paper_trail.rb index 5f8061a8..048c6983 100644 --- a/test/dummy/config/initializers/paper_trail.rb +++ b/test/dummy/config/initializers/paper_trail.rb @@ -1,3 +1,5 @@ -class Version < ActiveRecord::Base - attr_accessible :created_at, :updated_at, :answer, :action, :question, :article_id, :ip, :user_agent, :title +module PaperTrail + class Version < ActiveRecord::Base + attr_accessible :created_at, :updated_at, :answer, :action, :question, :article_id, :ip, :user_agent, :title + end end diff --git a/test/functional/controller_test.rb b/test/functional/controller_test.rb index 122ad146..ddef80b8 100644 --- a/test/functional/controller_test.rb +++ b/test/functional/controller_test.rb @@ -34,7 +34,7 @@ class ControllerTest < ActionController::TestCase assert_equal 0, w.versions.length delete :destroy, :id => w.id 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 test 'create' do @@ -62,7 +62,7 @@ class ControllerTest < ActionController::TestCase assert_equal 1, w.versions.length delete :destroy, :id => w.id 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 153, versions_for_widget.last.whodunnit.to_i assert_equal '127.0.0.1', versions_for_widget.last.ip diff --git a/test/paper_trail_test.rb b/test/paper_trail_test.rb index 596515f3..3bb78f0e 100644 --- a/test/paper_trail_test.rb +++ b/test/paper_trail_test.rb @@ -2,7 +2,7 @@ require 'test_helper' class PaperTrailTest < ActiveSupport::TestCase test 'Sanity test' do - assert_kind_of Module, PaperTrail + assert_kind_of Module, PaperTrail::Version end test 'create with plain model class' do @@ -21,7 +21,7 @@ class PaperTrailTest < ActiveSupport::TestCase widget = Widget.create assert_equal 1, widget.versions.length 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 end end diff --git a/test/unit/inheritance_column_test.rb b/test/unit/inheritance_column_test.rb index 6ae94089..e75baaa4 100644 --- a/test/unit/inheritance_column_test.rb +++ b/test/unit/inheritance_column_test.rb @@ -21,19 +21,19 @@ class InheritanceColumnTest < ActiveSupport::TestCase end 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 @animal.versions.first.reify.nil? @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. # 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 dog_versions.first.reify.nil? 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 cat_versions.first.reify.nil? cat_versions[1..-1].each { |v| assert_equal 'Cat', v.reify.class.name } diff --git a/test/unit/model_test.rb b/test/unit/model_test.rb index 1af4b6f2..ff16fe98 100644 --- a/test/unit/model_test.rb +++ b/test/unit/model_test.rb @@ -4,16 +4,16 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase context 'A record with defined "only" and "ignore" attributes' do 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 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 context 'which updates an ignored column and a selected column' do 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 assert_equal(2, @article.versions.size) @@ -26,7 +26,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase context 'which updates a selected column' do 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 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 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 context 'which updates a skipped column' do 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 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.' } - 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 assert_equal(2, @article.versions.size) @@ -73,7 +73,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase context 'which gets destroyed' do 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 assert_equal(2, @article.versions.size) @@ -86,7 +86,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase context 'which updates an ignored column' do 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 @@ -95,16 +95,16 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase context 'for non-US translations' do 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 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 context 'after destroy' do 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 @@ -117,22 +117,22 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase @translation.save 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 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 'that are not drafts' do 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 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 assert_equal(2, @translation.versions.size) @@ -141,7 +141,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase context 'after destroy' do 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 assert_equal(2, @translation.versions.size) @@ -297,15 +297,15 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase setup do @fluxor = @widget.fluxors.create :name => 'flux' @widget.destroy - @reified_widget = Version.last.reify + @reified_widget = PaperTrail::Version.last.reify end should 'record the correct event' do - assert_match /destroy/i, Version.last.event + assert_match /destroy/i, PaperTrail::Version.last.event end 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 should 'be available in its previous version' do @@ -536,7 +536,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase setup do PaperTrail.whodunnit = 'Charlie' @widget.destroy - @version = Version.last + @version = PaperTrail::Version.last end should 'track who made the change' do @@ -558,10 +558,10 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase end should 'reify with the correct type' do - thing = Version.last.reify + thing = PaperTrail::Version.last.reify assert_kind_of FooWidget, thing - assert_equal @foo.versions.first, Version.last.previous - assert_nil Version.last.next + assert_equal @foo.versions.first, PaperTrail::Version.last.previous + assert_nil PaperTrail::Version.last.next end should 'should return the correct originator' do @@ -574,10 +574,10 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase setup { @foo.destroy } should 'reify with the correct type' do - thing = Version.last.reify + thing = PaperTrail::Version.last.reify assert_kind_of FooWidget, thing - assert_equal @foo.versions[1], Version.last.previous - assert_nil Version.last.next + assert_equal @foo.versions[1], PaperTrail::Version.last.previous + assert_nil PaperTrail::Version.last.next end end end @@ -840,35 +840,35 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase end should 'store version on source <<' do - count = Version.count + count = PaperTrail::Version.count @book.authors << @dostoyevsky - assert_equal 1, Version.count - count - assert_equal Version.last, @book.authorships.first.versions.first + assert_equal 1, PaperTrail::Version.count - count + assert_equal PaperTrail::Version.last, @book.authorships.first.versions.first end should 'store version on source create' do - count = Version.count + count = PaperTrail::Version.count @book.authors.create :name => 'Tolstoy' - assert_equal 2, Version.count - count - assert_same_elements [Person.last, Authorship.last], [Version.all[-2].item, Version.last.item] + assert_equal 2, PaperTrail::Version.count - count + assert_same_elements [Person.last, Authorship.last], [PaperTrail::Version.all[-2].item, PaperTrail::Version.last.item] end should 'store version on join destroy' do @book.authors << @dostoyevsky - count = Version.count + count = PaperTrail::Version.count @book.authorships(true).last.destroy - assert_equal 1, Version.count - count - assert_equal @book, Version.last.reify.book - assert_equal @dostoyevsky, Version.last.reify.person + assert_equal 1, PaperTrail::Version.count - count + assert_equal @book, PaperTrail::Version.last.reify.book + assert_equal @dostoyevsky, PaperTrail::Version.last.reify.person end should 'store version on join clear' do @book.authors << @dostoyevsky - count = Version.count + count = PaperTrail::Version.count @book.authorships(true).clear - assert_equal 1, Version.count - count - assert_equal @book, Version.last.reify.book - assert_equal @dostoyevsky, Version.last.reify.person + assert_equal 1, PaperTrail::Version.count - count + assert_equal @book, PaperTrail::Version.last.reify.book + assert_equal @dostoyevsky, PaperTrail::Version.last.reify.person end end @@ -1038,17 +1038,17 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase 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 } context 'which is then saved' do setup { @post.save } 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 - 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 } 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 setup { @post.update_attributes({ :content => "Some new content" }) } 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 assert_nil @post.versions.last.changeset end @@ -1287,9 +1287,9 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase # Updates `model`'s last version so it looks like the version was # created 2 seconds ago. 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 - Version.record_timestamps = true + PaperTrail::Version.record_timestamps = true end end diff --git a/test/unit/timestamp_test.rb b/test/unit/timestamp_test.rb index b707ea13..05e451b2 100644 --- a/test/unit/timestamp_test.rb +++ b/test/unit/timestamp_test.rb @@ -5,8 +5,8 @@ class TimestampTest < ActiveSupport::TestCase setup do PaperTrail.timestamp_field = :custom_created_at change_schema - Version.connection.schema_cache.clear! - Version.reset_column_information + PaperTrail::Version.connection.schema_cache.clear! + PaperTrail::Version.reset_column_information Fluxor.instance_eval <<-END has_paper_trail diff --git a/test/unit/version_test.rb b/test/unit/version_test.rb index 27e2003d..527d00ba 100644 --- a/test/unit/version_test.rb +++ b/test/unit/version_test.rb @@ -1,55 +1,55 @@ require 'test_helper' -class VersionTest < ActiveSupport::TestCase +class PaperTrail::VersionTest < ActiveSupport::TestCase setup { change_schema @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 - Version.creates.each do |version| + PaperTrail::Version.creates.each do |version| assert_equal "create", version.event end end end - context "Version.updates" do + context "PaperTrail::Version.updates" do setup { @article.update_attributes(:name => 'Animal') - assert Version.updates.present? + assert PaperTrail::Version.updates.present? } should "return only update events" do - Version.updates.each do |version| + PaperTrail::Version.updates.each do |version| assert_equal "update", version.event end end end - context "Version.destroys" do + context "PaperTrail::Version.destroys" do setup { @article.destroy - assert Version.destroys.present? + assert PaperTrail::Version.destroys.present? } should "return only destroy events" do - Version.destroys.each do |version| + PaperTrail::Version.destroys.each do |version| assert_equal "destroy", version.event end end end - context "Version.not_creates" do + context "PaperTrail::Version.not_creates" do setup { @article.update_attributes(:name => 'Animal') @article.destroy - assert Version.not_creates.present? + assert PaperTrail::Version.not_creates.present? } 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 end end