I’m doing a recreational Rails project in my infrequent spare time and using RSpec as well. After generating a controller for the
1
|
Game
|
class I noticed it failed on a very simple specification.
controller.should_be_an_instance_of GameController
The failure message was:
undefined method 'an_instance_of?' for #<GameController:0x222df78>
That looked pretty wrong. Why was it trying to call
1
|
an_instance_of?
|
. It turns out
1
|
a
|
and
1
|
an
|
are just syntactic sugar methods that just return
1
|
self
|
. So just for fun I changed to the dot notation without the underscore sugar.
controller.should.be.an.instance.of GameController
That passed with flying colors. OK, so now I know it’s just an issue with the underscores. Writing a spec to show the issue was fairly simple:
context "Underscore Example Error" do specify "should_be_an_instance_of fails with underscore notation" do lambda { "example".should_be_an_instance_of String }.should_raise NoMethodError end specify "should.be.an.instance.of fails with underscore notation" do lambda { "example".should_not_be_an_instance_of Fixnum }.should_raise NoMethodError end specify "should_be_a_kind_of should fails underscore notation" do lambda { "example".should_be_a_kind_of Object }.should_raise NoMethodError end specify "should.not_be_a_kind_of fails with underscore notation" do lambda { "example".should_not_be_a_kind_of Fixnum }.should_raise NoMethodError end end
The bug appears to be with the following method in
def method_missing(sym, *args, &block) if __is_sweetened? sym object = self calls = sym.to_s.split("_") while calls.length > 1 call = calls.shift object = object.__send__(call) break if call == "be" end return object.__send__(calls.join("_"), *args, &block) end __orig_method_missing(sym, *args, &block) end
Hopefully tonight I’ll have time to code up a quick suggested patch and submit it. First I have to download a few gems and run the tests specs for RSpec to see if I might have broken something else with my fix.
I’m enjoying forcing myself to really think about contexts, specifications, and should statements instead of tests. I think I could probably accomplish about the same thing with good old
1
|
Test::Unit
|
, but forcing your brain to think down a different path can sometimes change your perspective.