MongoDoc
Version: Hurricane (0.6.2) 2010/06/25
Notes
This version of MongoDoc works with Rails 31
Quick Start
- install MongoDB (at least 1.4.0)
- install the Ruby driver
gem install mongo
- install the native extensions for BSON
gem install bson_ext
- install MongoDoc
gem install mongo_doc
- run an example from this directory
ruby -Ilib examples/simple_object.rb
Introduction
MongoDoc is a simple and easy to use ActiveRecord-like object mapper for mongoDB in Ruby.
MongoDoc is also an extension of the Mongo Ruby Driver making it a snap to get Ruby in and out of mongoDB.
MongoDoc is not ActiveRecord for mongoDB. We do not have callbacks, nor do we have dynamic finders. We do have associations, named scopes, and other features.
MongoDoc is simple, easy-to-use, and fast. And it works with Rails 3.
MongoDoc is designed to work with document data, if you are looking to map relational data in mongoDB, you will have to look elsewhere.
Ruby objects in mongoDB
Lets just get right into it and save some Ruby objects in mongoDB!
class Contact
attr_accessor :name, :addresses, :interests
end</code>
<code>class Address
attr_accessor :street, :city, :state, :zip, :phone_number
end
With MongoDoc, instead of saving JSON2, we can save an object directly:
contact = Contact.new
contact.name = 'Hashrocket'
contact.interests = ['ruby', 'rails', 'agile']</code>
<code>address = Address.new
address.street = '320 First Street North, #712'
address.city = 'Jacksonville Beach'
address.state = 'FL'
address.zip = '32250'
address.phone_number = '877 885 8846'
contact.addresses = [address]</code>
<code>collection.save(contact)
We can query using the powerful mongoDB query syntax, and have it return Ruby objects:
in_fl = collection.where('addresses.state' => 'FL')
in_fl_hashrocket = in_fl.where('name' => /rocket/)
puts in_fl_hashrocket.first.addresses.first.phone_number
Take a look in the examples directory for more code.
Mapping Documents
MongoDoc provides ActiveRecord-like persistence, associations, named scopes, and validations (from Validatable) as well as a mongoDB query language (from Mongoid). MongoDoc also plays nicely with Rails.
MongoDoc::Document
provides all these features as a mixin. A MongoDoc::Document
can either be a top-level mongoDB document, or an embedded document contained within a top-level document. Top-level documents are stored in collections named after their class: Contact
objects are stored in the ‘contacts’ collection (much like ActiveRecord).
Lets define a Contact
document with an Address
embedded document:
class Address
include MongoDoc::Document</code>
<code> attr_accessor :street
attr_accessor :city
attr_accessor :state
attr_accessor :zip_code
attr_accessor :phone_number
end</code>
<code>class Contact
include MongoDoc::Document</code>
<code> attr_accessor :name
attr_accessor :interests
embed_many :addresses</code>
<code> scope :in_state, lambda {|state| where('addresses.state' => state)}
end
Since a mongoDB document has no fixed schema, we define the composition of a document directly in our classes. We can also specify associations using embed
, embed_many
, and embed_hash
(similar to ActiveRecord’s has_one
and has_many
.
Building and saving a document is easy:
contact = Contact.new(:name => 'Hashrocket', :interests => ['ruby', 'rails', 'agile'])
contact.addresses << Address.new(:street => '320 1st Street North, #712',
:city => 'Jacksonville Beach',
:state => 'FL',
:zip_code => '32250',
:phone_number => '877 885 8846')
contact.save
Now that we have some data, we can query using our named scope:
hashrocket_in_fl = Contact.in_state('FL').where(:name => /rocket/)
hashrocket_address = hashrocket_in_fl.first.addresses.first
And we can even perform partial updates:
hashrocket_address.update_attributes(:street => '320 First Street North, #712')
Installation
MongoDoc requires mongoDB v1.4.0 or later.
% gem install mongo_doc
Connecting
By default, MongoDoc will read its configuration from ./mongodb.yml
. If that file does not exist, it will attempt to connect to a standard MongoDB local server setup and use a database name of "mongodoc"
.
With Rails
If you are using Rails, MongoDoc will look for its configuration in config/mongodb.yml
. If that file does not exist, it will attempt to connect to a standard MongoDB local server setup and use a database name of #{Rails.root.basename}_#{Rails.env}
.
Database configuration file
The file is similar to the Rails database.yml file, with environment definitions containing the database configuration attributes. For example:
development:
name: development
host: localhost
port: 27017
options:
auto_reconnect: true
test:
name: test
host: localhost
port: 27017
options:
auto_reconnect: true
If you are not using Rails, the default environment is development
and you can set the current environment in your code:
MongoDoc::Connection.env = 'test'
You can also change the location of the configuration file:
MongoDoc::Connection.config_path = './config/mongodb.yml'
Programmatically setting the database connection information
Finally, if you do not want to use the database configuration file, you can also set the database name, host, port, options, and strict values directly; for example, to set the database name to stats
:
MongoDoc::Connection.name = 'stats'
Cleaning the database during testing
When testing you may need to clean up and return the database to an empty state. MongoDoc::DatabaseCleaner.clean_database
is a helper that can be used to do this, for example with RSpec
(note the require
):
require 'mongo_doc/database_cleaner'
RSpec.configure do |config|
config.before(:each) do
MongoDoc::DatabaseCleaner.clean_database
end
end
Credits
Les Hill, leshill on github
Thanks
Thanks to Sandro and Durran for some great conversations and some lovely code.
Thanks to Elliot for pushing me to get Rails 3 support
Note on Patches/Pull Requests
- Fork the project.
- Make your feature addition or bug fix.
- Add tests for it. This is important so I 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 I can ignore when I pull)
- Send me a pull request. Bonus points for topic branches.
Copyright
Copyright © 2009 – 2010 Les Hill. See LICENSE for details.
1 If you are using Rails 2.3.x you need to be using the mongo_doc_rails2
gem from the rails2 branch on github
2 The Ruby driver exposes an API that understands JSON.