diff --git a/Gemfile.lock b/Gemfile.lock index ded33b5..6cfc75b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - acts_as_revisionable (1.2.3.sermo) + acts_as_revisionable (1.3.0.sermo) activerecord (~> 3.2) GEM diff --git a/lib/acts_as_revisionable.rb b/lib/acts_as_revisionable.rb index 4246865..038799d 100644 --- a/lib/acts_as_revisionable.rb +++ b/lib/acts_as_revisionable.rb @@ -32,6 +32,7 @@ module ActsMethods # acts_as_revisionable :meta => { # :updated_by => :last_updated_by, # :label => lambda{|record| "Updated by #{record.updated_by} at #{record.updated_at}"}, + # :before_store_revision => :callback_executed_on_read_only_object_to_be_versioned # :version => 1 # } # @@ -202,7 +203,7 @@ def last_revision end # Call this method to implement revisioning. The object changes should happen inside the block. - def store_revision + def store_revision(*args) if new_record? || @revisions_disabled return yield else @@ -213,7 +214,11 @@ def store_revision begin read_only = self.class.first(:conditions => {self.class.primary_key => self.id}, :readonly => true) if read_only - revision = read_only.create_revision!(self) + callback = self.class.acts_as_revisionable_options[:before_store_revision] + if callback + read_only.send(self.class.acts_as_revisionable_options[:before_store_revision], *args) + end + revision = read_only.create_revision! truncate_revisions! end rescue => e @@ -244,17 +249,17 @@ def store_revision end # Build a revision record based on this record - def build_revision(base_record = self) + def build_revision revision_options = self.class.acts_as_revisionable_options revision = revision_record_class.new(self, revision_options[:encoding]) - set_revision_meta_attributes(revision_options[:meta], revision, base_record) + set_revision_meta_attributes(revision_options[:meta], revision) revision end # Create a revision record based on this record and save it to the database. - def create_revision!(base_record = self) - revision = build_revision(base_record) + def create_revision! + revision = build_revision revision.save! revision end @@ -298,18 +303,17 @@ def update_with_revision end end - def set_revision_meta_attributes(meta_options, revision, base_record = self) + def set_revision_meta_attributes(meta_options, revision) if meta_options.is_a?(Hash) meta_options.each do |attribute, value| set_revision_meta_attribute(revision, attribute, value) end elsif meta_options.is_a?(Array) meta_options.each do |attribute| - set_revision_meta_attributes(attribute, revision, base_record) + set_revision_meta_attribute(revision, attribute, attribute.to_sym) end elsif meta_options - value = base_record.send(meta_options) - set_revision_meta_attribute(revision, meta_options, value) + set_revision_meta_attribute(revision, meta_options, meta_options.to_sym) end end diff --git a/lib/acts_as_revisionable/version.rb b/lib/acts_as_revisionable/version.rb index 7e20e1e..ce3ad3e 100644 --- a/lib/acts_as_revisionable/version.rb +++ b/lib/acts_as_revisionable/version.rb @@ -1,3 +1,3 @@ module ActsAsRevisionable - VERSION = '1.2.3.sermo' + VERSION = '1.3.0.sermo' end diff --git a/spec/acts_as_revisionable_spec.rb b/spec/acts_as_revisionable_spec.rb index ff6ea0e..04afcd2 100644 --- a/spec/acts_as_revisionable_spec.rb +++ b/spec/acts_as_revisionable_spec.rb @@ -107,19 +107,36 @@ class OtherRevisionableTestModel < ActiveRecord::Base class AnotherRevisionableTestModel < ActiveRecord::Base connection.create_table(table_name) do |t| t.string :name - t.string :updated_by end unless table_exists? - attr_accessor :label - acts_as_revisionable :meta => :label, :class_name => RevisionRecord2 + + attr_reader :label, :updated_by + acts_as_revisionable :before_store_revision => :set_info, + :class_name => "RevisionRecord2", + :meta => [:label, :updated_by] + + private + + def set_info(text, who) + @label = text + @updated_by = who + end end class YetAnotherRevisionableTestModel < ActiveRecord::Base connection.create_table(table_name) do |t| t.string :name - t.string :updated_by end unless table_exists? - attr_accessor :label, :album - acts_as_revisionable :meta => [:label, :album], :class_name => RevisionRecord3 + + attr_reader :label + acts_as_revisionable :before_store_revision => :set_label, + :class_name => "RevisionRecord2", + :meta => :label + + private + + def set_label + @label = 'WOW! It works!' + end end module ActsAsRevisionable @@ -233,30 +250,6 @@ class RevisionableSubclassModel < RevisionableNamespaceModel ActsAsRevisionable::RevisionRecord.count.should == 1 end - it "should bring non-database backed accessor values forward into revisions if used as meta data" do - record = AnotherRevisionableTestModel.new(:name => "test") - record.label = "Alternative Tentacles" - record.save! - record.store_revision do - record.name = "new name" - record.save! - end - record.last_revision.label.should == "Alternative Tentacles" - end - - it "should bring an array of non-database backed accessor values forward into revisions if used as meta data" do - record = YetAnotherRevisionableTestModel.new(:name => "test") - record.label = "Alternative Tentacles" - record.album = "Fresh Fruit for Rotting Vegetables" - record.save! - record.store_revision do - record.name = "new name" - record.save! - end - record.last_revision.label.should == "Alternative Tentacles" - record.last_revision.album.should == "Fresh Fruit for Rotting Vegetables" - end - it "should always store revisions whenever a record is saved if :on_update is true" do record = OtherRevisionableTestModel.create!(:name => "test") record.name = "new name" @@ -316,6 +309,29 @@ class RevisionableSubclassModel < RevisionableNamespaceModel ActsAsRevisionable::RevisionRecord.count.should == 1 end + describe "call back options" do + it "should call the provided function with passed data" do + record = AnotherRevisionableTestModel.create!(:name => "Larry Bo-Barry") + + record.store_revision("ding", "dong") do + record.name = "Sally Sally" + record.save! + end + record.last_revision.label.should == "ding" + record.last_revision.updated_by.should == "dong" + end + + it "should call the provided function if it doesn't take data" do + record = YetAnotherRevisionableTestModel.create!(:name => "Larry Bo-Barry") + + record.store_revision do + record.name = "Sally Sally" + record.save! + end + record.last_revision.label.should == "WOW! It works!" + end + end + describe "metadata" do context "when creating a revision record" do it "should set metadata on the revison using a complex attribute to value mapping" do