aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortechnoweenie <technoweenie@567b1171-46fb-0310-a4c9-b4bef9110e78>2007-08-13 19:25:23 +0000
committertechnoweenie <technoweenie@567b1171-46fb-0310-a4c9-b4bef9110e78>2007-08-13 19:25:23 +0000
commit18106f50a2623fa529d8c0a50aa72dc59f6ef3ce (patch)
tree98224857ff4c9c090d41d1cb6e12d39cd645629c
parent5d616cddd3334ac48f48a59c3471f12dd8dea388 (diff)
add methods for paging between versions, like @page.versions.before(@page_version) or @page_version.previous
git-svn-id: http://svn.techno-weenie.net/projects/plugins/acts_as_versioned@2947 567b1171-46fb-0310-a4c9-b4bef9110e78
-rw-r--r--lib/acts_as_versioned.rb65
-rw-r--r--test/versioned_test.rb31
2 files changed, 74 insertions, 22 deletions
diff --git a/lib/acts_as_versioned.rb b/lib/acts_as_versioned.rb
index 804d8e835..aabd78f6d 100644
--- a/lib/acts_as_versioned.rb
+++ b/lib/acts_as_versioned.rb
@@ -49,6 +49,21 @@ module ActiveRecord #:nodoc:
# page.revert_to(page.versions.last) # using versioned instance
# page.title # => 'hello world'
#
+ # page.versions.earliest # efficient query to find the first version
+ # page.versions.latest # efficient query to find the most recently created version
+ #
+ #
+ # Simple Queries to page between versions
+ #
+ # page.versions.before(version)
+ # page.versions.after(version)
+ #
+ # Access the previous/next versions from the versioned model itself
+ #
+ # version = page.versions.latest
+ # version.previous # go back one version
+ # version.next # go forward one version
+ #
# See ActiveRecord::Acts::Versioned::ClassMethods#acts_as_versioned for configuration options
module Versioned
CALLBACKS = [:set_new_version, :save_version_on_create, :save_version?, :clear_changed_attributes]
@@ -184,7 +199,7 @@ module ActiveRecord #:nodoc:
self.non_versioned_columns = [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column]
self.version_association_options = {
:class_name => "#{self.to_s}::#{versioned_class_name}",
- :foreign_key => "#{versioned_foreign_key}",
+ :foreign_key => versioned_foreign_key,
:order => 'version',
:dependent => :delete_all
}.merge(options[:association_options] || {})
@@ -199,7 +214,17 @@ module ActiveRecord #:nodoc:
end
class_eval do
- has_many :versions, version_association_options
+ has_many :versions, version_association_options do
+ # finds earliest version of this record
+ def earliest
+ @earliest ||= find(:first)
+ end
+
+ # find latest version of this record
+ def latest
+ @latest ||= find(:first, :order => 'version desc')
+ end
+ end
before_save :set_new_version
after_create :save_version_on_create
after_update :save_version
@@ -222,8 +247,30 @@ module ActiveRecord #:nodoc:
# create the dynamic versioned model
const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do
def self.reloadable? ; false ; end
+ # find first version before the given version
+ def self.before(version)
+ find :first, :order => 'version desc',
+ :conditions => ["#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version]
+ end
+
+ # find first version after the given version.
+ def self.after(version)
+ find :first, :order => 'version',
+ :conditions => ["#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version]
+ end
+
+ def previous
+ self.class.before(self)
+ end
+
+ def next
+ self.class.after(self)
+ end
end
+ versioned_class.cattr_accessor :original_class
+ versioned_class.original_class = self
+ puts versioned_class.original_class.inspect
versioned_class.set_table_name versioned_table_name
versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym,
:class_name => "::#{self.to_s}",
@@ -263,24 +310,12 @@ module ActiveRecord #:nodoc:
end
end
- # Finds a specific version of this model.
- def find_version(version)
- return version if version.is_a?(self.class.versioned_class)
- return nil if version.is_a?(ActiveRecord::Base)
- find_versions(:conditions => ['version = ?', version], :limit => 1).first
- end
-
- # Finds versions of this model. Takes an options hash like <tt>find</tt>
- def find_versions(options = {})
- versions.find(:all, options)
- end
-
# Reverts a model to a given version. Takes either a version number or an instance of the versioned model
def revert_to(version)
if version.is_a?(self.class.versioned_class)
return false unless version.send(self.class.versioned_foreign_key) == self.id and !version.new_record?
else
- return false unless version = find_version(version)
+ return false unless version = versions.find_by_version(version)
end
self.clone_versioned_model(version, self)
self.send("#{self.class.version_column}=", version.version)
diff --git a/test/versioned_test.rb b/test/versioned_test.rb
index b1109eb0c..b912500f9 100644
--- a/test/versioned_test.rb
+++ b/test/versioned_test.rb
@@ -4,6 +4,7 @@ require File.join(File.dirname(__FILE__), 'fixtures/widget')
class VersionedTest < Test::Unit::TestCase
fixtures :pages, :page_versions, :locked_pages, :locked_pages_revisions, :authors, :landmarks, :landmark_versions
+ set_fixture_class :page_versions => Page::Version
def test_saves_versioned_copy
p = Page.create! :title => 'first title', :body => 'first body'
@@ -209,8 +210,6 @@ class VersionedTest < Test::Unit::TestCase
def test_version_order
assert_equal 23, pages(:welcome).versions.first.version
assert_equal 24, pages(:welcome).versions.last.version
- assert_equal 23, pages(:welcome).find_versions.first.version
- assert_equal 24, pages(:welcome).find_versions.last.version
end
def test_track_changed_attributes
@@ -246,10 +245,10 @@ class VersionedTest < Test::Unit::TestCase
def test_find_versions
assert_equal 2, locked_pages(:welcome).versions.size
- assert_equal 1, locked_pages(:welcome).find_versions(:conditions => ['title LIKE ?', '%weblog%']).length
- assert_equal 2, locked_pages(:welcome).find_versions(:conditions => ['title LIKE ?', '%web%']).length
- assert_equal 0, locked_pages(:thinking).find_versions(:conditions => ['title LIKE ?', '%web%']).length
- assert_equal 2, locked_pages(:welcome).find_versions.length
+ assert_equal 1, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%weblog%']).length
+ assert_equal 2, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%web%']).length
+ assert_equal 0, locked_pages(:thinking).versions.find(:all, :conditions => ['title LIKE ?', '%web%']).length
+ assert_equal 2, locked_pages(:welcome).versions.length
end
def test_with_sequence
@@ -308,4 +307,22 @@ class VersionedTest < Test::Unit::TestCase
landmarks(:washington).attributes = landmarks(:washington).attributes.inject({}) { |params, (key, value)| params.update key => value.to_s }
assert !landmarks(:washington).changed?
end
-end
+
+ def test_should_find_earliest_version
+ assert_equal page_versions(:welcome_1), pages(:welcome).versions.earliest
+ end
+
+ def test_should_find_latest_version
+ assert_equal page_versions(:welcome_2), pages(:welcome).versions.latest
+ end
+
+ def test_should_find_previous_version
+ assert_equal page_versions(:welcome_1), page_versions(:welcome_2).previous
+ assert_equal page_versions(:welcome_1), pages(:welcome).versions.before(page_versions(:welcome_2))
+ end
+
+ def test_should_find_next_version
+ assert_equal page_versions(:welcome_2), page_versions(:welcome_1).next
+ assert_equal page_versions(:welcome_2), pages(:welcome).versions.after(page_versions(:welcome_1))
+ end
+end \ No newline at end of file