= has_many_versions This attempts to provide versioning for 'has many' relationships within ActiveRecord. == Installation script/plugin install git://github.com/joshbuddy/has_many_versions.git == Usage Here is a pretty typical relationship. class Book < ActiveRecord::Base belongs_to :author validates_associated :author end class Author < ActiveRecord::Base has_many :books end Lets say we want to include versioning now to modifications made to the collection of books. We can modify the +has_many+ relationship the following way: has_many :books, :extend => HasManyVersions Now changes made to the relationship with the normal << and +delete+ methods will be tracked. There are some modifications needed for both tables for this to work. The owner of the relationship (in this case +Author+) needs an integer column named +version+ (with a default value of one). The collection (in this case +Book+) needs two columns, +initial_version+ and +version+. Assuming we've done all that, lets try out some magical versioning to see how it all works. We'll start by defining some books. the_eyre_affair = Book.new(:name => 'The Eyre Affair') => # lost_in_a_good_book = Book.new(:name => 'Lost in a Good Book') => # the_well_of_lost_plots = Book.new(:name => 'The Well of Lost Plots') => # something_rotten = Book.new(:name => 'Something Rotten') => # And an author to take them. jasper = Author.new(:name => 'Jasper Fforde') => # That sounds good. Just so we're all on the same page, how does Jasper look at the moment? jasper.version => 1 jasper.books => [] Version 1 is where all versioned objects initially start. Now, lets start adding some books. jasper.books.push(the_eyre_affair, something_rotten) And our new version? jasper.version => 2 And our books? jasper.books => [#, #] Yeah! Everything is good and green. Lets add on some more books. jasper.books.push(lost_in_a_good_book) jasper.version => 3 jasper.books.push(the_well_of_lost_plots) jasper.version => 4 Because we did them one at a time, the version number incremented for each one. Now, Jasper has a *lot* of books. jasper.books => [#, #, #, #] Lets take one away... jasper.books.delete(lost_in_a_good_book) And the version has incremented jasper.version => 5 jasper.books => [#, #, #] But thats not right, he *did* write that book. Lets go back in time. jasper.books.rollback And the version get incremented... jasper.version => 6 And the books... jasper.books => [#, #, #, #] Are right where we left them! In fact, lets roll it right back to version 2. jasper.books.rollback(2) jasper.version => 7 jasper.books => [#, #] And what would the world look like if Jasper Fforde hadn't written anything? jasper.books.rollback(1) #back to version one jasper.version => 8 jasper.books => []