Friday, March 11, 2011

Ruby Light #4

eval_string.rb
class EvalString < String
def eval(b)
b.eval String.new(self)
end
end


irb session
>> foo = 1
=> 1
>> bar = 2
=> 2
>> str = EvalString.new "foo+bar"
=> "foo+bar"
>> str
=> "foo+bar"
>> str.eval(binding)
=> 3

Thursday, March 10, 2011

Ruby Light #3

This insanity is my own:

generic_test_helper.rb
require 'flexmock'

module GenericTestHelper
include FlexMock::TestCase

TIMESTAMP_MATCHER = '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+]\d{2}:\d{2}'

def clear_mocked_method(mock, method)
return unless mock.is_a? FlexMock

mock.instance_eval { @expectations.delete method.to_sym }
end

def mock_method(mock, method, retval, with = nil)
mock = flexmock mock unless mock.is_a? FlexMock
clear_mocked_method mock, method

if with.nil?
mock.should_receive(method).and_return retval
else
mock.should_receive(method).with(with).and_return retval
end
end
end


foo_test.rb
require 'generic_test_helper'
class FooTest < Test::Unit::TestCase
include GenericTestHelper

def test_exceptions_are_logged
exception = nil
begin
1 / 0
rescue Exception => exception
end

mock_database_lookups
clear_mocked_method Bar.instance_eval{@flexmock_proxy}.mock, :find_by_id
flexmock(Bar).should_receive(:find_by_id).and_raise(exception)

assert_nothing_raised { Foo.run 0 }
assert_match /exception caught: #{Regexp.escape exception.message} #{exception.backtrace.map{|str| Regexp.escape(str)}.join "\n#{TIMESTAMP_MATCHER}" }/,
@stdout.string
end
end

Friday, March 04, 2011

LXRing Ruby

As those of you who follow me on StackOverflow already know (Anyone? Bueller? Anyone?), I need to browse the source code of the Ruby interpreter. Getting no immediate answer, I set up LXR myself:

: josh@josh; cat /etc/issue
Ubuntu 10.10 \n \l
: josh@josh; sudo aptitude install apache2 lxr
: josh@josh; sudo vim /etc/apache2/sites-available/default
: josh@josh; tail -6 /etc/apache2/sites-available/default
Alias /lxr /usr/share/lxr

Options All
AllowOverride All

: josh@josh; sudo vim /usr/share/lxr/http/.htaccess
: josh@josh; sudo cat /usr/share/lxr/http/.htaccess

SetHandler cgi-script

: josh@josh; sudo mkdir -p /usr/share/lxr/source/1.8.7-p334
: josh@josh; cd /usr/share/lxr/source/1.8.7-p334
: josh@josh; sudo tar xvjf /tmp/ruby-1.8.7.tar.bz2
: josh@josh; sudo mv ruby-1.8.7 ruby
: josh@josh; sudo vim /usr/share/lxr/source/versions
: josh@josh; sudo cat /usr/share/lxr/source/versions
1.8.7-p334
: josh@josh; sudo ln -s /usr/share/lxr/source/1.8.7-p334 /usr/share/lxr/source/defversion
: josh@josh; sudo genxref ruby
Starting pass 1: Collect identifier definitions.
(Pass 1) vms/vmsruby_private.c (993), file 1 of 262…
[...]
(Pass 3) identifier 8200 of maximum 17136…
(Pass 3) identifier 8300 of maximum 17136…
Completed pass 3 (0s):Information on 8316 identifiers dumped to disk.
: josh@josh; sudo chmod -R o+r .
: josh@josh; sudo vim /usr/share/lxr/http/lxr.conf
: josh@josh; sudo cat /usr/share/lxr/http/lxr.conf
# Configuration file.
# [...]
# The source is here.
sourceroot: /usr/share/lxr/source/$v/ruby/
srcrootname: Ruby
# [...]

Thursday, March 03, 2011

Ruby Light #2

This is the work of one of my colleagues here at TestFreaks, and is the coolest little meta-programming trick I've seen in a while!

code_timer_helper.rb
module CodeTimerHelper

# Creates a CodeTimer section around the method
#
def timed_method(timer, method_name, section_name = method_name.to_s)
eigenclass = (class << self; self; end)
eigenclass.class_eval do

define_method method_name do |*args, &block|
timer.start(section_name)
begin
super(*args, &block)
ensure
timer.stop(section_name)
end
end
end
end
end