March 26, 2010

Posted by John

Tagged gems, harmony, and mongomapper

Older: Canable: The Flesh Eating Permission System

Newer: Because Gem Names Are Like Domains in the 90's

A Nunemaker Joint

Since The Changelog has already scooped me (darn those guys are fast), I figured I should post something here as well. Last December I posted Getting a Grip on GridFS. Basically, I liked what Grip was doing, but made a few tweaks. Grip’s development has continued, but it is headed down a bit different path, so I thought it might be confusing to keep my fork named the same.

Today, I did some more work on the project and now that it is unrecognizable when compared to Grip, I renamed it to Joint. Yes, I realize that I now have gems named crack and joint. Joint is a tiny piece of code that joins MongoMapper and the new Ruby GridFS API.


What I love about joint is its simplicity. Simply declare the attachment and you are good to go.

class Asset
  include MongoMapper::Document
  plugin Joint # add the plugin

  attachment :file # declare an attachment named image

With that simple declaration, you get #file and #file= instance methods and several keys (file_id, file_name, file_type, and file_size). The #file instance method returns a simple proxy to make the API a bit prettier and sends all other calls on the proxy to the GridIO instance.

asset = Asset.create(:file => params[:file])   # GridFS Object Id # file name
asset.file.type # mime type as determined by wand gem
asset.file.size # size in bytes

There is no limit to the number of attachments, but each attachment uses 4 keys so I would not add more than one or two (more is a sign you are doing something wrong). As mentioned in the comment above, it uses my wand project to determine the mime type.

For those that are not familiar with wand (as I have not posted here about it), it first attempts to determine the mime type using the mime-types gem. If that fails to returning anything, it drops down to the unix file command.

What It Does Not Do

Anything else. All joint handles is assigning a file and storing it in GridFS. It doesn’t do versions, resizing, etc. For this type of stuff, I would recommend imagery with some HTTP caching (varnish, et el.) sitting in front of it.

I can certainly see having some triggers (callbacks) at some point such as after jointed or something for when you do want to do post processing. I’ll leave that for a rainy day though.


  1. Fantastic work. I shall certainly be using this. I’ve been using the GridFS api in the ruby driver the last few days and it’s been great. But having something that ties in with mongomapper so cleanly and makes it this easy is terrific.

  2. Why is attaching more than 2 files a bad idea or a sign that I am doing something wrong?

  3. @Gustavo: Each attachment adds 4 keys. 2 attachments is 8 keys. I guess at some point you don’t want to have a bunch of keys in your document. Instead, I would lean toward and asset model and then let your documents have many assets. The asset model would only need one attachment. I guess it just feels cleaner to me that way.

  4. I think your comment against ‘attachment :file’ in the Asset model should say ‘# declare an attachment named file’.

    Very nice plugin though, I’ll certainly try it out. Thanks!

Sorry, comments are closed for this article to ease the burden of pruning spam.


Authored by John Nunemaker (Noo-neh-maker), a programmer who has fallen deeply in love with Ruby. Learn More.


Release your software more often with fewer problems.
Flip your features.