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: http://github.com/technoweenie/acts_as_versioned http://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 (c) 2010, 2013 Virginia Department of Education, released under the MIT license