Performance Benchmarking Ruby with MiniTest

A handy feature of MiniTest is the performance benchmarking assertions. Here's an example testing a couple of methods that are constant and linear in time as a function of their inputs:

require 'rubygems'
require 'minitest/benchmark'
require 'minitest/autorun'

class Thing
  def constant_time_method(n)
    true # O(1)
  end
  
  def linear_time_method(n)
    n.times { |i| constant_time_method(i) } # O(n)
  end
end

class AwesomeTest < MiniTest::Unit::TestCase
  def setup
    @thing = Thing.new
  end
  
  def test_constant_time_method_performance
    assert_performance_constant 0.99999 do |n|
     @thing.constant_time_method(n)
    end
  end
  
  def test_linear_time_method_performance
    assert_performance_linear 0.9999 do |n|
      @thing.linear_time_method(n)
    end
  end
end

Whilst I wouldn't go nuts with this, it's a nice solution for when you have optimized some code and want to add a check against regressions.

Scope the source and docs for more details.

Backport 1.9.3 load fixes to 1.9.2 with RVM

$ wget http://redmine.ruby-lang.org/attachments/download/1958/ruby-1.9.2-p290-load-path-backport.diff
$ rvm install 1.9.2-p290 --patch ruby-1.9.2-p290-load-path-backport.diff

This cut the load time for Rails 3 environment for a complex project from 31 seconds down to 15, and has been running fine with no issues for 2 few weeks.

Made of Code Theme for Xcode 4

A port of my TextMate theme, "Made of Code". Being a comic genius, I call it "Made of Xcode". It only works with Xcode 4.

To install download it and copy to ~/Library/Developer/Xcode/UserData/FontAndColorThemes. Restart Xcode and you can select it (Preferences > Fonts & Colors).

It’s the ephemeral but very real sense when you first make contact with the product that someone really truly understands you.

Awesome Rubygem for Gmail

A small selection of what you can do:

require "gmail"

Gmail.connect(username, password) do |gmail|
  gmail.logged_in?

  gmail.inbox.count
  gmail.inbox.count(:unread)
  gmail.inbox.count(:read)

  gmail.inbox.find(:unread) do |email|
    email.read!
    email.attachments[0].save_to_file("/path/to/location")
  end
end

(thx @bbergher)

Designing Beautiful Ruby APIs

Slides from a talk given by Wen-Tien Chang (@ihower) at Ruby Conf China 2010.

They're an amazingly rich source of information, especially the second half on Ruby's object model and meta-programming. If you use Ruby, you must read them!

Ruby Core Extension: Array#sum

It always bugs me that there is no #sum method on Arrays in Ruby. It's pretty easy to make your own:

class Array
  def sum
    inject(0) { |sum, i| sum + i }
  end
end

If you really want to be terse, you can use Symbol#to_proc:

class Array
  def sum
    inject(&:+) 
    # i.e. inject(&proc { |obj, *args| obj.send(:+, *args) })
  end
end

You could even just skip Symbol#to_proc, and pass in the method name you want to call on each accumulation:

class Array
  def sum
    inject(:+) 
    # i.e. inject { |sum, i| sum.send(:+, i) }
  end
end

However, I'm going to stick with the first version because I think it's clearer in the final implementation:

class Array
  def sum(method = nil, &block)
    if block_given?
      raise ArgumentError, "You cannot pass a block and a method!" if method
      inject(0) { |sum, i| sum + yield(i) }
    elsif method
      inject(0) { |sum, i| sum + i.send(method) }
    else
      inject(0) { |sum, i| sum + i }
    end
  end
end

This accepts no arguments, a method or a block. So, you can write things like:

>> [1,2,3].sum
=> 6
>> [1,2,3].sum(:to_f)
=> 6.0
>> [1,2,3].sum(&:to_f)
=> 6.0
>> [1,2,3].sum { |i| i+1 }
=> 9

ActiveSupport core extensions: Module

ActiveSupport provides some very handy additions the Module class, including attr_accessor_with_default, attr_internal_accessor, included_in_classes and synchronize, amongst others.

TextMate bundles: Rails, HAML, SASS + Shoulda

An awesome set of TextMate bundles for Ruby, Rails, HAML, SASS and Shoulda from phuibonhoa. This script backs up any existing bundles you’ve installed with the same name first, then installs all of the ones above.

A mix of code and design by Mark Dodwell, Rails developer and designer.

Older entries →