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?

Original source