Friday, April 27, 2007

Checking if a method called in transaction

Sometimes it's comforting to know your method is called within a transaction.


if Thread.current['open_transactions'].nil? ||
Thread.current['open_transactions'] == 0


will do. Any better idea?

Monday, April 23, 2007

Using Singleton Method

Ruby has some good features such as you can define/override a method just for one specific object. Basically you can do this:

(in irb)


class A
end

a = A.new
b = A.new

def a.one
1
end

irb(main):007:0> a.one
=> 1

irb(main):007:0> b.one
NoMethodError: undefined method `one' for #
from (irb):11
from :0


This feature is coming in handy when you want to mock out an instance method for a specific object.

Mocha can do this as well, but for an ActiveRecord object, it looks like do something like (assuming a is an ActiveRecord object)


a.expects(:some_method).returns(something)


has unpredictable behavior. Sometimes Mocha complains actual calls is 0 even though we do call some_method in the code being tested. We suspect it's because somehow Mocha couldn't find this specific object. If you change the statement to:


A.any_instance.expects(:some_method).returns(:some_thing)


where A is the type of a.

Then it works just fine, but we are not quite comfortable with this.

And in case if we want to mock out the same method on two different objects and behaves differently, Mocha is no help. In this case, we can use Singleton method to do the mocking:


...
def a.some_method
something
end

def b.some_method
something_else
end
...


This will effectively mock out the method some_method and has no side effect. Pretty neat.