Storing IP addresses the smarter way

If you need to store an IP address in a database, it’s possibly because you’re logging web requests or similar. This means the table can get very large, very quickly. If you’re storing the addresses in a VARCHAR, you will use up a lot of space in your table and make indexing a nightmare. A lot of people don’t know that you can represent these as an INT which is much more db-friendly.

IPv4 addresses are just 32-bit integers. In most languages (including in MySQL itself, useful for Sphinx indexes) you can use the equivalent of inet_ntoa(3) to convert to string and inet_aton(3) to convert to an int. In Ruby  however this is hidden inside the IPAddr class. This instantiation can be quite expensive for what is really a simple conversion, so you can use the following:

def inet_aton ip
  ip.split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first
end


def inet_ntoa n
  [n].pack("N").unpack("C*").join "."
end

Storing these correctly can save huge performance headaches later.

Running Goliath on a UNIX domain socket

EventMachine supports listening on UNIX domain sockets, therefore Goliath does too.

Simply create a config file as per the instructions on the wiki with the following:

@port = nil

This makes EventMachine take the address parameter as a unix socket, so simply run your server in the following way:

ruby hello_world.rb -sva hello_world.sock

You can then serve it up using nginx:

http {
  server {
    listen 80 default;
    
    location / {
      proxy_pass http://unix:///Users/boffbowsh/code/hello_world/hello_world.sock;
    }
  }
}

Rails 3: Shoulda failing to load

If you’re trying to test a Rails 3 gem/plugin/engine and you’re using Bundler, you’re likely to run into an error like the following:

DEPRECATION WARNING: RAILS_ROOT is deprecated! Use Rails.root instead. 
/Library/Ruby/Gems/1.8/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:40:in `join': can't convert # into String (TypeError)
from /Library/Ruby/Gems/1.8/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:40:in `autoload_macros'

You can easily fix this by making the autoload of macros a no-op, and loading them later once the app is defined:

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'precious'

require 'test/unit'

# No-op the auto load
require 'shoulda/autoload_macros'
module Shoulda; class <<self; alias :original_autoload_macros :autoload_macros; def autoload_macros *a; end; end; end
require 'shoulda'

class Test::Unit::TestCase
  def app_factory &blk
    klass = Class.new Rails::Application
    klass.class_eval(&blk) if block_given?
    Shoulda.original_autoload_macros File.dirname(__FILE__)
    klass
  end 
end

Rails 3: no such file to load — thor/group

If you’re getting errors about loading thor when trying to run the Rails 3 binary, try the following:

ruby -r'rubygems' railties/bin/rails

You can also alias this in your .profile or .bashrc for fun and profit:

alias rails3="ruby -r'rubygems' ~/gems/rails/railties/bin/rails"

Routing in Rails 3 Engines

If you’re creating a new Engine in Rails 3 (or upgrading one from Rails 2), you’re probably wondering how to do the routing. This is how:

Rails.application.routes.draw do
  namespace :admin do
    resources     :users
    resource      :session
    match         'login'  => 'admin/sessions#new', :as => 'login'
    match         'logout' => 'admin/sessions#destroy', :as => 'logout'
    root          :to => 'admin/home#index'
  end
end

Note that in Rails 3, non-resource routes (like root, login and logout above) don’t obey the namespace context when selecting the controller. This requires you to match specifically to admin/sessions rather than simply sessions.

Rubinius dependencies on Ubuntu

If you’re trying to build Rubinius on a blank Ubuntu install, you’ll likely hit missing dependancies such as readline, ossl_typ.h and readline. When you run ./configure, it’ll also says that backtrace isn’t found.

Make sure you’ve got the following packages installed, and all will be well:

ruby-dev
zlib1g-dev
libssl-dev
libreadline-dev