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.
