| Module | ActiveRecord::Acts::Versioned::ClassMethods |
| In: |
lib/acts_as_versioned.rb
|
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
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
# 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