ActsAsEdition
acts_as_edition is a ruby gem for creating new editions of a tree (think document) of ActiveRecord models.
Each new edition tree is a deep clone of the previous tree. The edition tree is defined using an acts_as_edition declaration on each model in the tree. Using the resources option, acts_as_edition supports management of relationships between models in the edition tree and those outside it. A selection of hooks provide additional control over the cloning process. Conditions can be specified on models in the tree to determine when/if they are cloned. Finally, each object in the tree maintains a simple belongs_to relationship with its ancestor in the previous edition.
If you are considering acts_as_edition, you should also evaluate acts_as_versioned and deep_cloning:
github.com/technoweenie/acts_as_versioned github.com/DefV/deep_cloning
Install
gem install acts_as_edition
For ActiveRecord < 4.0.0 use:
gem install acts_as_edition --version '=1.0.1'
Example
First, add ancestor_id column to every table in the tree, using a migration thusly:
class AddEditionMigration < ActiveRecord::Migration
def self.up
add_column :mymodel, :ancestor_id, :integer
end
def self.down
remove_column :mymodel, :ancestor_id
end
end
rake db:migrate
Then declare acts_as_edition in the model class:
class Guide < ActiveRecord::Base
acts_as_edition :edition_chain => [:abbreviation, :imprint, :places],
:resources => [:country, :retailers, :authors],
:pre_hook => :unpublish_self,
:after_clone => :increment_descendant_year,
:post_hook => :publish_descendant
:conditions => { :returns_true => true }
has_one :abbreviation
belongs_to :imprint
has_many :places
has_one :country
has_many :retailers
has_and_belongs_to_many :authors
protected
def unpublish_self
self.published = false
self.save!
end
def increment_descendant_year
self.year = (self.year.to_i + 1).to_s
self.save!
end
def publish_descendant
self.descendant.published = true
self.descendant.save!
end
def returns_true
name != 'Noclonelandia'
end
end
class Abbreviation < ActiveRecord::Base
. . .
end
And so on – these models are taken from the tests if you need more context.
To clone:
new_edition = Guide.first.clone_edition! new_edition.ancestor # == Guide.first Guide.first.descendant # == new_edition
Attributes listed in edition_chain are cloned. Note that their model classes must also have acts_as_edition declarations.
Atributes listed in resources are not cloned. The relationship between these resource objects and objects in the previous edition tree are reestablished in the new edition tree. NOTE: the relatishionship of the resource to the original object may be broken. The exception is resources in a habtm relationship with edition objects. In these cases, the relationship to the new edition is additive.
pre_hook and post_hook are called at the beginning and end of the process on the original object. The after_clone hook is called *on the newly cloned object* before it is saved to the database.
If an object does not meet all conditions specified in the conditions options hash, clone_edition! on that object will return nil and the object will not be copied into the new tree.
Copyright © 2010, 2013 Virginia Department of Education, released under the MIT license