I recently went through an exercise of upgrading one of Artsy’s largest web projects to the current HEAD of Mongoid 4.x. This is going to be a major release with numerous changes and I wanted to flush out bugs before the final version of the ODM is released. All Mongoid changes currently live on master.

gem 'mongoid', github: 'mongoid/mongoid'

In the process I’ve worked on making a few gems compatible with Mongoid 4 and learned a couple of things that should help you make this process smooth for your own applications.


Moped’s BSON implementation has been removed in favor of the MongoDB bson gem 2.0 and higher. All Moped::BSON references must change to BSON. This is rather annoying and forces many libraries to have to fork behavior at runtime.

module Mongoid
  def self.mongoid3?
    ::Mongoid.const_defined? :Observer # deprecated in Mongoid 4.x

  def self.mongoid2?
    ::Mongoid.const_defined? :Contexts # deprecated in Mongoid 3.x

The mongoid2? implementation is borrowed from mongoid_orderable and I wrote the mongoid3? version by parsing the CHANGELOG - observers are deprecated in 4.0.

Now, instead of calling Moped::BSON::ObjectId.legal?(id), you have to do something like this:

if Mongoid.mongoid3?
  Moped::BSON::ObjectId.legal? id
  BSON::ObjectId.legal? id

Furthermore, you can no longer convert a string into a Moped::BSON::ObjectId(id), you must explicitly call from_string:

if Mongoid.mongoid3?

Libraries should then adjust their dependencies on Mongoid and specify >= 3.0, and maybe < 5.0.

Testing Against Multiple Mongoid Versions

The mongoid-orderable gem has a neat system for testing against all versions of Mongoid with Travis CI. First, the .travis.yml file declares a test matrix that sets MONGOID_VERSION. Note that Mongoid 3.x or newer doesn’t run with Ruby 1.8.x or 1.9.2.

```ruby .travis.yml rvm:

  • 1.8.7
  • 1.9.2
  • 1.9.3
  • ruby-head



matrix: exclude: - rvm: 1.8.7 env: MONGOID_VERSION=3 - rvm: 1.8.7 env: MONGOID_VERSION=4 - rvm: 1.9.2 env: MONGOID_VERSION=3 - rvm: 1.9.2 env: MONGOID_VERSION=4

services: mongodb

The library's *Gemfile* locks a different version depending on the environment variable, defaulting to 3.x. You can also test against a very specific version, if you must.

```ruby Gemfile
source "http://rubygems.org"


case version = ENV['MONGOID_VERSION'] || "~> 3.1"
when /4/
  gem "mongoid", :github => 'mongoid/mongoid'
when /3/
  gem "mongoid", "~> 3.1"
when /2/
  gem "mongoid", "~> 2.8"
  gem "mongoid", version

Upgraded Gems

I used the above method to make a few gems Mongoid 4.x compatible, via the following pull requests.

Upgrading a Rails Project

If you’re using Rails, you’re in for upgrading both Mongoid 4.x and Rails to 4.x. This means you will suffer a lot of pain trying to find compatible versions of various interdependent gems. I suggest locking Rails, Mongoid and ActiveSupport to begin with.

``` ruby Gemfile gem ‘rails’, ‘4.0.1’ gem ‘activesupport’, ‘4.0.1’ gem ‘mongoid’, github: ‘mongoid/mongoid’

Bulk search & replace `Moped::BSON::ObjectId` references.

Calls to `inc`, `set` and `add_to_set` now take hashes, eg. `artist.inc(likes_count: 1)`.

If you're converting Mongoid objects to JSON and seeing data such as `{ "$oid" => "..." }` instead of an ID, monkey-patch `BSON::ObjectId.as_json`. See [this discussion thread](https://groups.google.com/forum/#!msg/mongoid/MaXFVw7D_4s/T3sl6Flg428J).

``` ruby config/initializers/bson/object_id.rb
module BSON
  class ObjectId
    def as_json(options = {})

If you’re using Warden (including via Devise) and/or rely on session cookies that may contain a user ID, add an implementation for the deprecated Moped::BSON::Document. This will prevent all old cookies from causing a serialization error and logging all those users out.

``` ruby config/initializers/bson/ module Moped module BSON ObjectId = ::BSON::ObjectId

class Document < Hash
  class << self
    def deserialize(io, document = new)
      __bson_load__(io, document)

    def serialize(document, io = "")
end   end end ```


Please post your updates below and questions to the mongoid mailing list. I’ll update this post up until Mongoid 4.x ships.

Categories: MongoDB, Mongoid