diff options
| author | technoweenie <technoweenie@567b1171-46fb-0310-a4c9-b4bef9110e78> | 2007-08-13 19:25:23 +0000 |
|---|---|---|
| committer | technoweenie <technoweenie@567b1171-46fb-0310-a4c9-b4bef9110e78> | 2007-08-13 19:25:23 +0000 |
| commit | 18106f50a2623fa529d8c0a50aa72dc59f6ef3ce (patch) | |
| tree | 98224857ff4c9c090d41d1cb6e12d39cd645629c | |
| parent | 5d616cddd3334ac48f48a59c3471f12dd8dea388 (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.rb | 65 | ||||
| -rw-r--r-- | test/versioned_test.rb | 31 |
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 |
