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>