Ruby metaprogramming, how does RSpec's 'should' work?
metaprogramming, rspec, ruby
Solution
Take a look at class OperatorMatcher.
It all boils down to Ruby allowing you to leave out periods and parenthesis. What you are really writing is:
target.should.send(:==, 5)
That is, send the message `should` to the object `target`, then send the message `==` to whatever `should` returns.
The method `should` is monkey patched into `Kernel`, so it can be received by any object. The `Matcher` returned by `should` holds the `actual` which in this case is `target`.
The `Matcher` implements the method `==` which does the comparison with the `expected` which, in this case, is the number 5. A cut down example that you can try yourself:
module Kernel
def should
Matcher.new(self)
end
end
class Matcher
def initialize(actual)
@actual = actual
end
def == expected
if @actual == expected
puts "Hurrah!"
else
puts "Booo!"
end
end
end
target = 4
target.should == 5
=> Booo!
target = 5
target.should == 5
=> Hurrah!
Problem
I was reading up on RSpec and I was trying to figure out how RSpec's "should" was implemented. Could someone give a hand on how the meta nature of this function works? The code is located here: http://github.com/dchelimsky/rspec/blob/master/lib/spec/expectations/extensions/kernel.rb TIA, -daniel Clarification: ``` target.should == 5 ``` How did target's value get passed along to "should", which in turn was "=="'d against 5?