Brian’s Code Blog

CouchDB presentation at Austin On Rails

I actually gave this presentation on CouchDB several months ago, but I didn't blog back then, so I thought I'd put it up now. This is a basic broad overview of what CouchDB is, what Ruby Libraries are available, and some example code on how to use them. With the latest release (0.10.0), I'm not sure if this is still 100% accurate, since it was written for 0.9, but it should be close. In case you were wondering, here are the Ruby Libraries avaiable:

Filed under  //   austinonrails   couchdb   presentation   ruby   slides  
Posted October 28, 2009
// 0 Comments

DataMapper is Schemaless, or can be

Inspired by How Friendfeed Uses Mysql I wanted to build a way to do that seamlessly. I took advantage of DataMapper's flexibility and built a plugin that allows me to do so.

Basics

It's pretty straight forward. The bare minimum to use it is:

  class Message
    include DataMapper::Resource

    is :schemaless
    
    # The following properties will be defined automatically
    # property :added_id, DataMapper::Types::Serial, :key => false 
    # property :id, DataMapper::Types::UUID, :unique => true, :nullable => false, :index => true
    # property :updated, DataMapper::Types::EpochTime, :key => true, :index => true
    # property :body, DataMapper::Types::Json
  end
  
Away you go! By default it creates keys and a few other fields. It adds a bit of method missing magic so any property you want automatically has name, name=, and name?. You should use these instead of accessing the body hash directly in order to keep nil indexes from being setup.

Indexes

Declaring indexes. Just use the class level index_on method and supply a symbol. This will create the association and a table called <property>Index. It also creates an update hook to monitor the record when its save and handle creating/updating/destroying the index record.

  class Message
    include DataMapper::Resource
  
    is :schemaless
  
    index_on :email
  end
  
Querying

This is handled for you automatically. After you create an index on a property whenever you use that in a query it will transform the query to look it up on the index table instead. So internally here's what happens.

  # original query
  Message.all(:email => 'test@gmail.com')
  # transformed query
  Message.all('email_index.email' => 'test@gmail.com')
  
This will also still support all of DM's query operators.

Props to Dan Kubb for all his awesome work on DM and helping fix/refine this code.

File all bugs as issues on the project http://github.com/BrianTheCoder/dm-is-schemaless

Filed under  //   datamapper   ruby   schemaless  
Posted October 26, 2009
// 0 Comments

Nginx Upload Module

So if you're doing any uploads in a ruby/rails webapp and nginx, you should be using the nginx upload module. In fact it'd work with any web app running nginx, but the conf file may be a little different. So why is the upload module so awesome? Lets start off going over a typical upload process in ruby:

  • File is sent to server
  • File is buffered by ruby
  • File is available for use
However, using the upload module the process goes like this:
  • File is sent to server
  • File is buffered by c
  • File is available for use
Guess which one is faster? This will take some tweaking to your app to get it to work. You can either create a new file instance from the file path variable or try using rack-uploads. I took the former route. On our staging server I noticed a huge speed increase. I didn't measure it, but is noticeably faster, espicially for larger files. So no the grand question: How do I use it? Well here's what I added to my nginx.conf file to make it work. If you're unfamiliar with nginx, these go inside the server block. Now this may not work perfect for you if you're not using unicorn. I was banging my head against the wall for a while trying to figure out why rails couldn't recognize the request. Turns out nginx doesn't forward the host by default. You can checkout the source here http://github.com/vkholodkov/nginx-upload-module. As for version compatibility:
  • 2.0.9 is compatible with nginx 0.6.x, 0.7.52-0.7.62, 0.8.1-0.8.8
  • 2.0.10 is compatible with nginx 0.6.x, 0.7.52-0.7.62, 0.8.1-0.8.16

Lastly, here's the conf bits, enjoy!

Filed under  //   nginx   ruby   upload_module  
Posted October 19, 2009
// 0 Comments

Using ngnix with Unicorn

So there's a new kid on the block in the ruby server world, Unicorn. The guys over at github have a good writeup on their blog about what it is and how to user it, that also posted a god config file to monitor it. Also if you want a good explanation of why unicorn is cool, check out Ryan Tomayko's article "I like Unicorn because it's Unix". One important note on both their unicorn config and their config, the paths they have are very specific to their setup. If you're running a normal capistrano setup, you'll want to store the sockets and pids in the shared directory rather than the current. So now the only part is the front end web server. This typically tends to be nginx(pronounced engine x) or apache these days, though litespeed and lighttpd are good as well. My personal choice is nginx, installing it and getting running is pretty easier and straight forward. All that's left to do is tweak the nginx.conf file. I used a modified version of ezra's nginx.conf file. Here's the conf with my optimizations:

Note if you're not using a socket just set the server in the upstream block to 127.0.0.1:<%=@port %>

Filed under  //   nginx   ruby   unicorn  
Posted October 13, 2009
// 0 Comments