Skip to content

Commit

Permalink
Add nicer syntax for simply copying attributes into revision metadata.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Durand committed Nov 22, 2011
1 parent d07b351 commit 9acc5ed
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 15 deletions.
36 changes: 24 additions & 12 deletions lib/acts_as_revisionable.rb
Expand Up @@ -5,10 +5,6 @@ module ActsAsRevisionable

autoload :RevisionRecord, File.expand_path('../acts_as_revisionable/revision_record', __FILE__)

def self.included(base)
base.extend(ActsMethods)
end

module ActsMethods
# Calling acts_as_revisionable will inject the revisionable behavior into the class. Specifying a :limit option
# will limit the number of revisions that are kept per record. Specifying :minimum_age will ensure that revisions are
Expand Down Expand Up @@ -39,6 +35,11 @@ module ActsMethods
# :version => 1
# }
#
# As a shortcut, you can can also just pass an attribute name or array of attribute names to copy to the revision
# record.
#
# acts_as_revisionable :meta => :updated_by
#
# The values to the <tt>:meta</tt> hash can be either symbols or Procs. If it is a symbol, the method
# so named will be called on the record being revisioned. If it is a Proc, it will be called with the
# record as the argument. Any other class will be sent directly to the revision record.
Expand Down Expand Up @@ -248,14 +249,14 @@ def create_revision!
revision = revision_record_class.new(self, revision_options[:encoding])
if revision_options[:meta].is_a?(Hash)
revision_options[:meta].each do |attribute, value|
case value
when Symbol
value = self.send(value)
when Proc
value = value.call(self)
end
revision.send("#{attribute}=", value)
set_revision_meta_attribute(revision, attribute, value)
end
elsif revision_options[:meta].is_a?(Array)
revision_options[:meta].each do |attribute|
set_revision_meta_attribute(revision, attribute, attribute.to_sym)
end
elsif revision_options[:meta]
set_revision_meta_attribute(revision, revision_options[:meta], revision_options[:meta].to_sym)
end
revision.save!
return revision
Expand Down Expand Up @@ -299,7 +300,18 @@ def update_with_revision
update_without_revision
end
end

# Set an attribute based on a meta argument
def set_revision_meta_attribute(revision, attribute, value)
case value
when Symbol
value = self.send(value)
when Proc
value = value.call(self)
end
revision.send("#{attribute}=", value)
end
end
end

ActiveRecord::Base.send(:include, ActsAsRevisionable)
ActiveRecord::Base.extend(ActsAsRevisionable::ActsMethods)
38 changes: 35 additions & 3 deletions spec/acts_as_revisionable_spec.rb
Expand Up @@ -143,7 +143,7 @@ class RevisionableSubclassModel < RevisionableNamespaceModel

context "injected methods" do
it "should be able to inject revisionable behavior onto ActiveRecord::Base" do
ActiveRecord::Base.included_modules.should include(ActsAsRevisionable)
ActiveRecord::Base.should respond_to(:acts_as_revisionable)
end

it "should add as has_many :record_revisions association" do
Expand Down Expand Up @@ -275,8 +275,8 @@ class RevisionableSubclassModel < RevisionableNamespaceModel
record_1.create_revision!
ActsAsRevisionable::RevisionRecord.count.should == 1
end
it "should set metadata on the revison when creating a revision record" do

it "should set metadata on the revison when creating a revision record using a complex attribute to value mapping" do
record_1 = OtherRevisionableTestModel.create!(:name => "test", :updated_by => "dude")
RevisionRecord2.count.should == 0
record_1.create_revision!
Expand All @@ -286,6 +286,38 @@ class RevisionableSubclassModel < RevisionableNamespaceModel
revision.updated_by.should == "dude"
revision.version.should == 1
end

it "should set metadata on the revison when creating a revision record using a simply string to define a method to copy" do
meta_value = OtherRevisionableTestModel.acts_as_revisionable_options[:meta]
begin
OtherRevisionableTestModel.acts_as_revisionable_options[:meta] = "label"
record_1 = OtherRevisionableTestModel.create!(:name => "test", :updated_by => "dude")
record_1.stub!(:label => "this is a label")
record_1.create_revision!
revision = record_1.last_revision
revision.label.should == "this is a label"
revision.updated_by.should == nil
revision.version.should == nil
ensure
OtherRevisionableTestModel.acts_as_revisionable_options[:meta] = meta_value
end
end

it "should set metadata on the revison when creating a revision record using an array of attribute names to copy" do
meta_value = OtherRevisionableTestModel.acts_as_revisionable_options[:meta]
begin
OtherRevisionableTestModel.acts_as_revisionable_options[:meta] = [:label, "version"]
record_1 = OtherRevisionableTestModel.create!(:name => "test", :updated_by => "dude")
record_1.stub!(:label => "this is a label", :version => 100)
record_1.create_revision!
revision = record_1.last_revision
revision.label.should == "this is a label"
revision.updated_by.should == nil
revision.version.should == 100
ensure
OtherRevisionableTestModel.acts_as_revisionable_options[:meta] = meta_value
end
end

it "should not create a revision entry if revisioning is disabled" do
record = RevisionableTestModel.create!(:name => "test")
Expand Down

0 comments on commit 9acc5ed

Please sign in to comment.