= dm-is-versioned DataMapper plugin enabling simple versioning of models. When a model is versioned, and updated, instead of the previous version being lost in the mists of time, it is saved in a subsidiary table, so that it can be restored later if needed. Please Note! this gem behaves differently to how AR's :acts_as_versioned works. There is currently no multi version storage possible. == Installation === Stable Install the dm-is-versioned gem. $ (sudo)? gem install dm-is-versioned === Edge Download or clone dm-is-versioned from Github[http://github.com/datamapper/dm-is-versioned/]. $ cd /path/to/dm-is-versioned $ rake install # will install dm-is-versioned == Getting started To start using this gem, just require dm-is-versioned in your app. Lets say we have a Post class, and we want to retain the previous version of a post. Just do this: class Post include DataMapper::Resource property :id, Serial property :title, String property :body, Text property :updated_at, DateTime is_versioned :on => :updated_at ## this syntax also works # is :versioned, :on => :updated_at end That simple snippet will automatically create a second Post::Version model and a (post_versions) table in your DB when you auto migrate or auto upgrade: Post.auto_migrate! # => will run auto_migrate! on Post::Version, too Post.auto_upgrade! # => will run auto_upgrade! on Post::Version, too # or DataMapper.auto_migrate! # => will run auto_migrate! on Post::Version, too DataMapper.auto_upgrade! # => will run auto_upgrade! on Post::Version, too # don't forget to require 'dm-migrations' before you migrate. OK, now that we have a versioned model, let's see what we can do with it. == Usage We start with creating a new Post: post = Post.create(:title => 'A versioned Post title', :body => "A versioned Post body") # automatically saved When we create this Post, no secondary version is created. The versioning only takes place when we update our Post: post.title = "An updated & versioned Post title" post.save In the Post::Version (post_versions) table we would now find the previous version of the Post. This is how it would look like: # db.post table --------------------------------------------------------------------------------------- | id | title | body | updated_at | --------------------------------------------------------------------------------------- | 1 | 'An updated & versioned Post title' | 'A versioned Post body' | DateTime | # db.post_versions table --------------------------------------------------------------------------------------- | id | title | body | updated_at | --------------------------------------------------------------------------------------- | 1 | 'A versioned Post title' | 'A versioned Post body' | DateTime | === #versions Once you have a versioned model, you can retrieve the previous version, like this: old_post = post.versions.first => # Please Note! that the #versions method returns an array by default. That's basically what dm-is-versioned does. == Gotchas Now there are some gotcha's that might not be entirely obvious to everyone, so let's clarify them here. === Make sure the versioned trigger has a value In this type of scenario: class Post property :updated_at, DateTime is_versioned :on => :updated_at end You must ensure that the versioned trigger always has a value, either through: # using the dm-timestamps gem, which automatically updates the :updated_at attribute timestamps :at # or a callback method, that updates the value before save before(:save) { self.updated_at = Time.now } Without this, things just don't work. === Ensure you use dm-migrations gem The post_versions table is NOT created unless you migrate your models through: DataMapper.auto_migrate! / Post.auto_migrate! DataMapper.auto_upgrade! / Post.auto_upgrade! That’s about it. == Errors / Bugs If something is not behaving intuitively, it is a bug, and should be reported. Report it here: http://datamapper.lighthouseapp.com/ == TODOs * Make it work more like AR's :acts_as_versioned plugin, with support for multiple versions and so on. * Enable replacing a current version with an old version. * Anything else missing? == Note on Patches/Pull Requests * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so we don't break it in a future version unintentionally. * Commit, do not mess with rakefile, version, or history. * (if you want to have your own version, that is fine but bump version in a commit by itself we can ignore when we pull) * Send us a pull request. Bonus points for topic branches. == Copyright Copyright (c) 2011 Timothy Bennett. Released under the MIT License. See LICENSE for details. === Credits Credit also goes to these contributors[http://github.com/datamapper/dm-is-versioned/contributors].