More MongoMapper Awesomeness »
Created at: 09.10.2009 16:00, source: RailsTips - Home, tagged: mongodb mongomapper
September was a month of craziness and for the first month in quite a while I did not post here. I promise it hurt me as much as it hurt you. In an effort to get back in the rhythm, I am going to start with an easy article. MongoMapper has been getting a lot of love lately and I thought I would mention some of the awesomeness.
Dynamic Finders
Dynamic finders are so darn handy in ActiveRecord. How many times have you used User.find_by_email and the like? Thankfully David Cuadrado took a stab at it. I took what he started, tested it a bit harder and added it onto document associations as well. This means when you have a document with a many documents association, you can now use dynamic finders that are scoped to that association.
class User
include MongoMapper::Document
many :posts
end
class Post
include MongoMapper::Document
key :user_id, ObjectId
key :title, String
end
user = User.create
user.posts.create(:title => 'Foo')
# would return post we just created
user.posts.find_by_title('Foo')
Document associations now also have all the normal Rails association methods such as build, create, find, etc.
Logging
The mongo ruby driver added logging support so a few days ago, I added some basic support for accessing and using that logger from within MongoMapper. When you pass a logger instance to the ruby driver, you can access that connections logger instance from MongoMapper.logger like so:
logger = Logger.new('test.log')
MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, :logger => logger)
MongoMapper.logger # would be equal to logger
Tailing the log would give you output like the following:
MONGODB db.$cmd.find({"count"=>"statuses", "query"=>{"project_id"=>"4aceaabed072c4745f0003ca"}, "fields"=>nil})
MONGODB db.$cmd.find({"count"=>"statuses", "query"=>{"project_id"=>"4aceaabed072c4745f0003ce"}, "fields"=>nil})
The nifty part about this is you can setup your Mongo::Connection to use Rails.logger and then all your mongo queries show up in your Rails logs if you have your log level set low enough. This has been very handy for me working on MongoMapper because I can see exactly what MM is sending to Mongo behind the scenes.
Because of this addition, I noticed that every find(:first) was using :order => ‘$natural’ which doesn’t allow using indexes and leads to slow queries. I removed the default order so instead it is just a find with a limit of 1, which should help make a few parts perform better.
Dirty Attributes
ActiveRecord’s dirty attributes is such a cool feature that yesterday, I spent a few hours porting it to MongoMapper::Document. Now you can do things like:
class Foo
include MongoMapper::Document
key :phrase, String
end
foo = Foo.new
foo.changed? # false
foo.phrase_changed? # false
foo.phrase = 'Dirty!'
foo.changed? # true
foo.phrase_changed? # true
foo.phrase_change # [nil, 'Dirty!']
I’m sure there will be edge cases, but as we find them we can fortify the tests and go from there.
Custom Data Types
With the 0.4 release came the transition from typecasting to custom data types. Now, instead of natively defining typecasting for “allowed” data types, you can have any data type that you like. You just have to do the conversion to and from mongo yourself. Making your own data types is as simple as:
class Foo
def self.to_mongo(value)
# convert value to a mongo safe data type
end
def self.from_mongo(value)
# convert value from a mongo safe data type to your custom data type
end
end
class Thing
include MongoMapper::Document
key :name, Foo
end
This means each time the name of Thing is saved to mongo or pulled out of mongo it will be ran through the Foo#to_mongo and Foo#from_mongo to make sure it is exactly what you want it to be.
Out of the box, MongoMapper supports Array, Binary, Boolean, Date, Float, Hash, Integer, ObjectId, String, and Time. You can check out the support file and tests to see how this works.
Time Zones
One not on times, since I mentioned it above is that all times are stored in the datbase as utc now. Also, if you have Time.zone set, all times are converted to the current time zone going to and from the database. This actually turned out to be really easy. We’ll see if I did it all correctly once people start pounding on it I guess. :)
Lazy Loading
One thing that I’ve been working on in between other features is making MongoMapper more lazy. I have already made connection, database and collection lazy so MM doesn’t actually create the connection or connection to the database until needed which makes MM work a lot better with Rails.
I still need to make indexes lazy, so that is the next thing to tackle. I’m thinking once that is in, I’ll have something like MongoMapper.ensure_indexes!, similar to DataMapper.auto_migrate!, which actually ensures the indexes exist rather than doing that the second a class loads.
Internal Improvements
Along with all the public features, I have been working on the internals of MM whenever I get a chance. They still need cleaning up, but things are getting better. Along with some refactoring, I did some work to speed the tests up.
The tests were starting to creep up to around 40 seconds which was driving me nuts. I did a bit of work and realized that clearing every collection before every test was causing most of the slowdown so I pruned the functional tests to only clear the collections that were actually used in that test. This cut the time from around 40 seconds to 10. Yep, huge!
Conclusion
There are still rough parts and I would recommend MongoMapper for beginners, but if you can troubleshoot not only your own code but others, MM is in a good place for you. Up until now, I’ve been working on adding features that I needed similar to ActiveRecord, but I am almost to a place where I am going to start adding features to MM that can literally only exist because of MongoDB.
The next month is going to see some really cool things like upserts, modifiers ($set, $inc, $dec, $push, $pull, etc.) and the like make their way into MM. I also have some plans for an identity map implementation. Oooohs and aaaaaahs abound!
more »
MongoMapper Indy.rb Presentation »
Created at: 19.08.2009 18:08, source: RailsTips - Home, tagged: mongodb mongomapper presentation
In which I post slides and audio from my last MongoDB presentation.
Last Wednesday I was invited to present on MongoDB and MongoMapper at the Indianapolis ruby group. I promised them I would post the slides so they could get to the links and such.
Slides
The slides are very similar to my Grand Rapids presentation on MongoDB. but the actual talk was different.
<object height="355" width="425"><param /><param /><param /><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongodbindyrb-090819100052-phpapp01&stripped_title=mongodb-indyrb" height="355" width="425"></embed></object>Audio
On top of the slides, there is also some rough audio thanks to David Jones. You can listen to it here. I think in total it is around an hour. I’m to lazy to sync the slides and the audio so you’ll have to do that your self. :)
I made a joke that CouchDB sucks. It was a joke. I actually like Couch a lot, I just like Mongo better. :)
Also, there is an interview with Mike Dirolf on the strange loop conference blog about MongoDB with Python and Ruby that may be of interest to you.
That is all for now. Enjoy!
more »
MongoMapper Indy.rb Presentation »
Created at: 19.08.2009 18:08, source: RailsTips - Home, tagged: mongodb mongomapper presentation
Last Wednesday I was invited to present on MongoDB and MongoMapper at the Indianapolis ruby group. I promised them I would post the slides so they could get to the links and such.
Slides
The slides are very similar to my Grand Rapids presentation on MongoDB. but the actual talk was different.
Audio
On top of the slides, there is also some rough audio thanks to David Jones. You can listen to it here. I think in total it is around an hour. I’m to lazy to sync the slides and the audio so you’ll have to do that your self. :)
I made a joke that CouchDB sucks. It was a joke. I actually like Couch a lot, I just like Mongo better. :)
Also, there is an interview with Mike Dirolf on the strange loop conference blog about MongoDB with Python and Ruby that may be of interest to you.
That is all for now. Enjoy!
more »
Getting Started With MongoMapper and Rails »
Created at: 24.07.2009 01:17, source: RailsTips - Home, tagged: gems mongodb mongomapper video
In which I show how to get up and running with MongoMapper and Rails in both text and video formats.
I have had a few requests for tips on getting started with MongoDB and Rails so I thought I would drop some quick knowledge. It is actually really easy to get going, but Rails always does everything for you so when something comes along that doesn’t, you sometimes feel lost.
rails mongomapper_demo
cd mongomapper_demo
Now that your Rails shell is created, let’s add MongoMapper to the mix. Open up environment.rb. First, configure it as a gem, then remove ActiveRecord from the mix, and lastly, point it at a database.
Rails::Initializer.run do |config|
config.gem 'mongomapper', :version => '>= 0.2.1'
config.frameworks -= [:active_record]
end
MongoMapper.database = "myappname-#{Rails.env}"
As of now there are no fancy generators for your models (gasp!) so you can just create a new file in app/models and an accompanying file in test/unit. Or, if you like, you can use script generate like so and just adjust your model after it is created (until I or some kind soul gets around to generators).
script/generate model Note --skip-migration
Then you can just change your app/models/note.rb file to be something like this:
class Note
include MongoMapper::Document
key :title, String
key :body, String
end
I’d like to say there is more to it, but there isn’t. :) Don’t worry about creating your database or migrating it. It all happens on the fly.
Video
For those that prefer visual learning, I’ve even whipped together a short screencast where I install MongoDB on OSX, fire it up, and build a really basic note app. Enjoy!
more »
Getting Started With MongoMapper and Rails »
Created at: 24.07.2009 01:17, source: RailsTips - Home, tagged: mongodb mongomapper gems video
Warning: This is currently out of date as it was based on an older version of MongoMapper.
I have had a few requests for tips on getting started with MongoDB and Rails so I thought I would drop some quick knowledge. It is actually really easy to get going, but Rails always does everything for you so when something comes along that doesn’t, you sometimes feel lost.
rails mongomapper_demo
cd mongomapper_demo
Now that your Rails shell is created, let’s add MongoMapper to the mix. Open up environment.rb. First, configure it as a gem, then remove ActiveRecord from the mix, and lastly, point it at a database.
Rails::Initializer.run do |config|
config.gem 'mongomapper', :version => '>= 0.2.1'
config.frameworks -= [:active_record]
end
MongoMapper.database = "myappname-#{Rails.env}"
As of now there are no fancy generators for your models (gasp!) so you can just create a new file in app/models and an accompanying file in test/unit. Or, if you like, you can use script generate like so and just adjust your model after it is created (until I or some kind soul gets around to generators).
script/generate model Note --skip-migration
Then you can just change your app/models/note.rb file to be something like this:
class Note
include MongoMapper::Document
key :title, String
key :body, String
end
I’d like to say there is more to it, but there isn’t. :) Don’t worry about creating your database or migrating it. It all happens on the fly.
Video
For those that prefer visual learning, I’ve even whipped together a short screencast where I install MongoDB on OSX, fire it up, and build a really basic note app. Enjoy!
more »

