Setting Up Rails 4 with MongoDB and Mongoid

A short guide to setting up Rails 4 with MongoDB and Mongoid



Overview

If you've never checked out MongoDB before, I'd very much encourage you to. It's a NoSQL document store that makes for a very interesting method of development compared to relational databases. We've been using it a lot lately for prototyping at Efeqdev and have thoroughly enjoyed it. Today we're going to walk through installing it on Ubuntu and setting up Rails with MongoDB and Mongoid to replace ActiveRecord.

Installing MongoDB

First let's install MongoDB from their official repository:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
sudo echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" | tee -a /etc/apt/sources.list.d/10gen.list
sudo apt-get -y update
sudo apt-get -y install mongodb-10gen

If you run mongo in your shell you should get an interactive database prompt:

MongoDB shell version: 2.4.6
connecting to: test
>

Rails 4 with Mongoid

Next you're going to need to generate your Rails application with rails new myapp --skip-active-record. The --skip-active-record is important because it doesn't include ActiveRecord in the app that is generated. We need to modify the Gemfile to remove sqlite3 and add Mongoid.

You'll want to delete these lines from your Gemfile:

# Use sqlite3 as the database for Active Record
gem 'sqlite3'

And add these:

gem 'mongoid', '~> 4', github: 'mongoid/mongoid'
gem 'bson_ext'

The mongoid gem that supports Rails 4 hasn't been fully published yet so we're using it directly from their Github repository. Now that these are added you can run bundle to install the gems for your Rails app.

Now we need to generate the Mongoid configuration file that is very much like your config/database.yml that you may be used to with ActiveRecord. We'll create the mongoid file by running the following command:

rails g mongoid:config

This generates config/mongoid.yml which you can take a look at and make any configuration changes as necessary.

Conclusion

And that's all there is to it! While it's much more work than you might expect, I imagine this will become a smoother process in the future once the Rails 4 gem has been released. Be sure to check out Mongoid's documentation for more information on how to use it.



Discussion


Gravatar

If you have time could you please make a guide for OSX Users? :)

Gravatar

Only difference is you'll want to install Homebrew and then MongoDB through that using "brew install mongodb"


Gravatar
Wicky Andrian on

great tuts, thanks for help


Gravatar

This is an area I've studied a lot lately, because I have an interest in using NoSQL instead of SQL databases for some of my models. Since we're on Rails 5 and Mongoid 6 now, I just thought I'd share these steps for setting it up now:

1) Create your Rails app with the '--skip-active-record' switch.

2) Remove sqlite3 from your Gemfile, add Mongoid to your Gemfile, and run 'bundle'.

3) Run 'rails g mongoid:config'.

4) Check your 'application.rb' file and make sure that inside the 'class Application' there is the line " Mongoid.load! './config/mongoid.yml' ". It's sometimes not included when the config is generated, but it's needed to use Mongoid.

5) Mongoid is ready to go. The Rails generators for 'model', 'scaffold' etc have been overridden by Mongoid. Any models, scaffolds etc that you create will create classes that include the Mongoid::Document module instead of inheriting from ApplicationRecord in the models folder.

-----

And something I've also found useful is using both ActiveRecord and Mongoid. MongoDB works great for some types of data, but sometimes I still feel more comfortable with SQL for some data, especially if I feel the need to wrap it in transactions.

1) Create your Rails app.

2) Add Mongoid to your Gemfile and run 'bundle'.

3) Run 'rails g mongoid:config'.

4) Check your 'application.rb' file and make sure that inside the 'class Application' there is the line " Mongoid.load! './config/mongoid.yml' ". It's sometimes not included when the config is generated, but it's needed to use Mongoid.

5) Mongoid is ready to go. The Rails generators for 'model', 'scaffold' etc have been overridden by Mongoid. Any models, scaffolds etc that you create will create
classes that include the Mongoid::Document module instead of inheriting
from ApplicationRecord in the models folder.

6) The ActiveRecord generators are still available, you just need to specify to use the 'active_record' versions as you use them. For example, at this point 'rails g model user email' generates a Mongoid model but 'rails g active_record:model user email' generates an ActiveRecord model and creates the needed migration. If you chose to make this a Mongoid model, there is no migration to worry about. If you chose to make this an ActiveRecord model, run the migration with 'rails db:migrate'. (Rails 5 moved rake functionality into the rails command)

7) You can create associations between ActiveRecord and Mongoid models by manually coding methods. You'll need to consider foreign keys. For example, if an ActiveRecord User has many Mongoid Posts, you'd add a foreign key field to the Post model. Its type would be Integer since ActiveRecord models use the Integer type for their id. Keep in mind that queries made from these associations can be slower because they traverse two data stores. Take things like lazy loading and the n+1 problem into consideration.

-----

An example application I created while tinkering with this is here. I created the ActiveRecord User and Mongoid Post example: https://github.com/welkie/e...

Gravatar

Thanks for sharing all this Matt! Will be useful for anyone reading this as I think it was originally written for Mongoid 4.

It's great to hear that they finally got the ActiveRecord + Mongoid stuff working nicely. I remember it wasn't super doable last time I used it because of some incompatibility.

Gravatar

No problem. I think the only work they have done getting ActiveModel and Mongoid to play nice together is make sure the generators don't interfere with each other. I wasn't able to find any officially documented method of creating associations between models in different databases. And that's fair in my opinion. They're separate things, so I don't expect them to officially support each other. The method I describe above is my attempt at hacking something together.

If anybody can think of any pitfalls I might encounter and has any advice, I'd be happy to hear it!

Gravatar
Tiago Cassio on

Thanks for sharing Matt!

Gravatar
FirstByte Technologies on

Thank you, @mattwelke:disqus, for the updates!


Gravatar
Maueez Ahmed on

@mattwelke:disqus Hi there,
I want to ask that how can we use firebase database with rails. Since it is nosql database as well. Are the steps same as you mentioned for mongodb. There is a gem on firebase-rails but i can't seem to find any proper documentation.

Thanks

Gravatar

Sorry about that, never realized you posted.

Rails is usually about relying on opinionated libraries that act as ActiveRecord adapters. We have that for SQL and MongoDB and actually a few others too (I know of Dynamoid for AWS DynamoDB). You could try finding one for Firebase. I know you say you found one that seemed to lack good documentation, so perhaps you've already exhausted this option.

If you can't find one, another good option which is a bit lower level but still convenient is to have your model class inherit from ActiveModel and then add the needed methods to satisfy the ActiveModel interface. You'd provide methods for getting it by id, saving, etc. This would mean using the official Ruby gem for Firebase, or if one isn't available, use a gem like HTTParty to interact with its REST API. Then you can use it in your controllers and views as you would any ActiveRecord model. Because Firebase is a document database, using it will be very similar to using Mongo.

However, if you go this route, you won't have associations handled for you so you'll have to make navigation methods between your Firebase ActiveModels like I made between ActiveRecord and Mongoid in my example repo.

Because this method is so flexible, and it would work with any persistence layer, you should be able to find example tutorials online for making your own ActiveModels.

Gravatar
Maueez Ahmed on

great! Thanks for the help (Y)


Login or create an account to join the conversation.