Module ActiveRecord::Acts::Versioned::ClassMethods
In: lib/acts_as_versioned.rb

Methods

Included Modules

ActiveRecord::Acts::Versioned::ActMethods

Public Instance methods

Configuration options

  • class_name - versioned model class name (default: PageVersion in the above example)
  • table_name - versioned model table name (default: page_versions in the above example)
  • foreign_key - foreign key used to relate the versioned model to the original model (default: page_id in the above example)
  • inheritance_column - name of the column to save the model’s inheritance_column value for STI. (default: versioned_type)
  • version_column - name of the column in the model that keeps the version number (default: version)
  • limit - number of revisions to keep, defaults to unlimited
  • if - symbol of method to check before saving a new version. If this method returns false, a new version is not saved. For finer control, pass either a Proc or modify Model#version_condition_met?
      acts_as_versioned :if => Proc.new { |auction| !auction.expired? }
    

    or…

      class Auction
        def version_condition_met? # totally bypasses the <tt>:if</tt> option
          !expired?
        end
      end
    
  • if_changed - Simple way of specifying attributes that are required to be changed before saving a model. This takes either a symbol or array of symbols.

Database Schema

The model that you’re versioning needs to have a ‘version’ attribute. The model is versioned into a table called #{model}_versions where the model name is singlular. The _versions table should contain all the fields you want versioned, the same version column, and a #{model}_id foreign key field.

A lock_version field is also accepted if your model uses Optimistic Locking. If your table uses Single Table inheritance, then that field is reflected in the versioned model as ‘versioned_type’ by default.

Acts_as_versioned comes prepared with the ActiveRecord::Acts::Versioned::ActMethods::ClassMethods#create_versioned_table method, perfect for a migration. It will also create the version column if the main model does not already have it.

  class AddVersions < ActiveRecord::Migration
    def self.up
      # create_versioned_table takes the same options hash
      # that create_table does
      Post.create_versioned_table
    end

    def self.down
      Post.drop_versioned_table
    end
  end

[Source]

     # File lib/acts_as_versioned.rb, line 103
103:         def acts_as_versioned(options = {})
104:           # don't allow multiple calls
105:           return if self.included_modules.include?(ActiveRecord::Acts::Versioned::ActMethods)
106: 
107:           class_eval do
108:             include ActiveRecord::Acts::Versioned::ActMethods
109:             cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column, 
110:               :version_column, :max_version_limit, :track_changed_attributes, :version_condition
111:             attr_accessor :changed_attributes
112:           end
113:           
114:           self.versioned_class_name = options[:class_name] || "#{self.to_s.demodulize}Version"
115:           self.versioned_foreign_key = options[:foreign_key] || self.to_s.foreign_key
116:           self.versioned_table_name = options[:table_name] || "#{table_name_prefix}#{Inflector.underscore(Inflector.demodulize(class_name_of_active_record_descendant(self)))}_versions#{table_name_suffix}"            
117:           self.versioned_inheritance_column = options[:inheritance_column] || "versioned_#{inheritance_column}"
118:           self.version_column = options[:version_column] || 'version'
119:           self.max_version_limit = options[:limit].to_i
120:           self.version_condition = options[:if] || true
121: 
122:           class_eval do
123:             has_many :versions, 
124:               :class_name  => "ActiveRecord::Acts::Versioned::#{versioned_class_name}",
125:               :foreign_key => "#{versioned_foreign_key}",
126:               :order       => 'version'
127:             before_save  :set_new_version
128:             after_create :save_version_on_create
129:             after_update :save_version
130:             after_save   :clear_old_versions
131:             after_save   :clear_changed_attributes
132:             
133:             unless options[:if_changed].nil?
134:               self.track_changed_attributes = true
135:               options[:if_changed] = [options[:if_changed]] unless options[:if_changed].is_a?(Array)
136:               options[:if_changed].each do |attr_name|
137:                 define_method("#{attr_name}=") do |value|
138:                   (self.changed_attributes ||= []) << attr_name.to_s unless self.dirty?(attr_name) or self.send(attr_name) == value
139:                   write_attribute(attr_name.to_s, value)
140:                 end
141:               end
142:             end
143:           end
144:           
145:           # create the dynamic versioned model
146:           eval "class ActiveRecord::Acts::Versioned::\#{versioned_class_name} < ActiveRecord::Base\nset_table_name \"\#{versioned_table_name}\"\nbelongs_to :\#{self.to_s.demodulize.underscore}, :class_name => \"\#{self.to_s}\"\nend\n"
147:         end

[Validate]