Mongoid Versioning - A Run Down
In past Rails apps that I've built, I've used plugins such as vestal version or acts_as_versioned to version my ActiveRecord models in MySQL. Using Mongoid, you get that functionality built-in without the need for extra gems / plugins.
For the purposes of this discussion, let's use the following code as a reference point:
So.... what really goes on when you put that innocent include Mongoid::Versioning in your model? I'm glad you asked:
- A field named version of type Integer is added.
- An embeds_many association named versions is created with the :class_name option set as your current class. Using our example above the generated code would look like this: embeds_many :versions, :class => Post.
- A before_save callback is created that takes care of versioning the document.
Now that we've got the basics established lets go through some use cases that will better illustrate how versioning works.
- Let's say I have an idea for a new post and I create one with just a title. Then at some point in the future I finally get around to writing the content and save it to MongoDB.
Since we've completed 2 save operations, there will be two versions in the database and the document look something like this:
Notice in the versions array that the content field is actually not there. If a default is not defined on your field and you do not create anything the field will not be created in the document. - Now we've got our newly finished post in MongoDB and it's available for the world to see. At some point, a user decides to comment on our post and we need to save that to our document.
The document in the database will now look like this:
Notice that in this instance that a new version was not created when we saved an embedded document. This is great when you've got a setup like this and you don't want to create multiple versions.
Gotchas & Workarounds
- Take into consideration how you're going to create your embedded documents - By this I mean if you were to do something like this:
Mongoid will not only create a new comment but will also create a new version of the entire document - The entire contents of the document is saved in the version - When embedding something like comments on a post, depending on how many comments your had, that array of comments could get pretty big. Now if you were to update a field on the post and it had a large amount of comments, all of the comments would get saved in the old and new versions. Again depending on the size of the comments, this could quickly start taking up large amounts of disk space
- You can skip creating a version if need be - I wouldn't recommend this if you're trying to keep track of documents, but it can be done.
Note that :revise is the name of the method in Mongoid::Versioning and that I did this on the class Post and not an instance. I'm not sure if you can skip a callback on an instance. I'll have to look into that.
That's all I've got for now. As I continue to learn more about mongoid, I'll continue to post on this blog. Maybe I'll even turn this into a larger series on the ins and outs of using mongoid.
Posted 6/14/2010 06:13:00 AM - mongoid
WHO AM I?
I'm Rimas Silkaitis, a mild mannered Ruby dev living in San Francisco. I like building stuff for the web and am particularly interested in machine learning. I also own a set of turntables.
Posts

