Module: ActiveRecord::Acts::Versioned::ClassMethods
- Defined in:
- lib/acts_as_versioned.rb
Instance Method Summary collapse
-
#acts_as_versioned(options = {}) ⇒ Object
Configuration options.
Instance Method Details
#acts_as_versioned(options = {}) ⇒ Object
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) -
sequence_name
- name of the custom sequence to be used by the versioned model. -
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
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/acts_as_versioned.rb', line 104 def acts_as_versioned( = {}) # don't allow multiple calls return if self.included_modules.include?(ActiveRecord::Acts::Versioned::ActMethods) class_eval do include ActiveRecord::Acts::Versioned::ActMethods cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column, :version_column, :max_version_limit, :track_changed_attributes, :version_condition, :version_sequence_name attr_accessor :changed_attributes end self.versioned_class_name = [:class_name] || "#{self.to_s.demodulize}Version" self.versioned_foreign_key = [:foreign_key] || self.to_s.foreign_key self.versioned_table_name = [:table_name] || "#{table_name_prefix}#{Inflector.underscore(Inflector.demodulize(class_name_of_active_record_descendant(self)))}_versions#{table_name_suffix}" self.versioned_inheritance_column = [:inheritance_column] || "versioned_#{inheritance_column}" self.version_column = [:version_column] || 'version' self.version_sequence_name = [:sequence_name] self.max_version_limit = [:limit].to_i self.version_condition = [:if] || true class_eval do has_many :versions, :class_name => "ActiveRecord::Acts::Versioned::#{versioned_class_name}", :foreign_key => "#{versioned_foreign_key}", :order => 'version' before_save :set_new_version after_create :save_version_on_create after_update :save_version after_save :clear_old_versions after_save :clear_changed_attributes unless [:if_changed].nil? self.track_changed_attributes = true [:if_changed] = [[:if_changed]] unless [:if_changed].is_a?(Array) [:if_changed].each do |attr_name| define_method("#{attr_name}=") do |value| (self.changed_attributes ||= []) << attr_name.to_s unless self.changed?(attr_name) or self.send(attr_name) == value write_attribute(attr_name.to_s, value) end end end end # create the dynamic versioned model # maybe if i sit down long enough i can think up a better way to do this. dynamic_model = <<-EOV class ActiveRecord::Acts::Versioned::#{versioned_class_name} < ActiveRecord::Base set_table_name "#{versioned_table_name}" belongs_to :#{self.to_s.demodulize.underscore}, :class_name => "#{self.to_s}" EOV dynamic_model += %Q{set_sequence_name "#{version_sequence_name}"\n} if version_sequence_name eval dynamic_model + 'end' end |