Take the 2-minute tour ×

Mongoid has built-in versioning when you mix-in the Mongoid::Versioning module. It works really well for me but I'm inelegantly working with versions on a model. Let me give you an example. Assume I'm building a blog app (I'm not).

My model is Post. Let's say I wanted to find all previous published versions of a single post. The following works:

post = Post.first  # just grab something
published_posts = post.versions.find_all{ |v| v.published == true }

Etc. Then I could do something with published_posts or whatever. I'd love to make a named scope for this so I'm not putting the find_all block in my view but I can't figure out how to override the built-in functionality of the Version class.

I've tried various scopes in my Post class. For example:

# I can't get this and other variations on this to work
scope :versions_published, 
  :where => 'self.versions.find_all{ |v| v.published == true }'

I also tried monkey patching the Version class but it doesn't like it very much. I have a workaround, I was just hoping to learn more about the built-in Versioning Mongoid provides, especially how to extend the Version class.

share|improve this question

1 Answer 1

up vote 1 down vote accepted

The scope you've defined is very, very wrong for two fundamental reasons:

  1. You can't pass a string to the :where argument. You need to pass in a hash
  2. scopes are defined on the class (Post in this case), so you cannot reference self.versions since self refers to the Post class and not to any specific post

The solution is to use the matches helper in Mongoid (which is a shortcut to Mongo's $elemMatch):

class Post
  scope :versions_published, where(:versions.matches => {:published => true})

I would not recommend monkeypatching the Version class unless you really know what you are doing.

share|improve this answer

Your Answer


