lib/glue/revisable.rb in og-0.25.0 vs lib/glue/revisable.rb in og-0.26.0
- old
+ new
@@ -1,2 +1,124 @@
+module Glue
-raise 'This is not working yet, do not require this file.'
+# Revision support for Og-managed classes.
+#
+# class Article
+# is Revisable
+# property :body, String, :revisable => true
+# property :title, String
+# end
+#
+# Generates the Revision class:
+#
+# class Article::Revision
+#
+# article.revisions
+#
+# article.revise do |a|
+# a.title = 'hello'
+# a.body = 'world'
+# end
+#
+# article.rollback(4)
+
+module Revisable
+ # The revision of the revisable object.
+
+ property :revision, Fixnum
+
+ # This mixin is injected into the dynamically generated
+ # Revision class. You can customize this in your application
+ # to store extra fields per revision.
+
+ module Mixin
+ # The create time for the revision.
+
+ property :create_time, Time
+
+ # Override to handle your options.
+
+ def initialize(obj, options = {})
+ revision_from(obj)
+ @create_time = Time.now
+ end
+
+ def revision_from(obj)
+ for prop in obj.class.properties.values
+ # gmosx, FIXME: test against primary key, not oid.
+ unless prop.symbol == :oid
+ instance_variable_set "@#{prop}", obj.send(prop.to_s)
+ end
+ end
+ end
+
+ def revision_to(obj)
+ for prop in obj.class.properties.values
+ # gmosx, FIXME: test against primary key, not oid.
+ unless prop.symbol == :oid
+ obj.instance_variable_set "@#{prop}", self.send(prop.to_s)
+ end
+ end
+ end
+ alias_method :apply_to, :revision_to
+ end
+
+ def self.included(base)
+ super
+
+ base.module_eval %{
+ class Revision < #{base}
+ include Revisable::Mixin
+ belongs_to #{base}
+ end
+ }
+
+ base.has_many :revisions, base::Revision
+ end
+
+ # Can accept options like owner or a comment.
+ # You can specialize this in your app.
+
+ def revise(options = {})
+ if self.revision.nil?
+ self.revision = 1
+ else
+ self.revision += 1
+ end
+ self.revisions << self.class::Revision.new(self, options)
+ yield(self) if block_given?
+ self.save
+ end
+ alias_method :revise!, :revise
+
+ # Rollback to an older revision.
+
+ def rollback(rev, options = {})
+ self.revise(options) { |obj| get_revision(rev).apply_to(obj) }
+ end
+
+ # Return a revision.
+
+ def get_revision(rev)
+ return self if rev.to_i == self.revision
+ self.revisions.find_one(:condition => "revision=#{rev}")
+ end
+
+ # Return the last revision.
+
+ def last_revision
+ self.revisions(:order => 'revision DESC', :limit => 1).first
+ end
+
+ # The number of revisions.
+
+ def revision_count
+ self.revisions.count
+ end
+ alias_method :revisions_count, :revision_count
+
+end
+
+end
+
+# * George Moschovitis <gm@navel.gr>
+# * Dirk Barnikel <dirk.barnikel@gmx.de>