0

From the RSpec docs:

require 'rspec/expectations'

RSpec::Matchers.define :be_a_multiple_of do |expected|
  match do |actual|
    actual % expected == 0
  end
end

RSpec.describe 9 do
  it { is_expected.to be_a_multiple_of(3) }
end

What is going on here? When defining a matcher what is this section of code:

:be_a_multiple_of do |expected|
      match do |actual|
        actual % expected == 0
      end
    end

Is that a Proc? What is being passed to the .define method? What is |expected|? Is that the 3 that we pass into the method? How does :be_a_multiple_of become a method? There seems to be a lot of metaprogrammy magic going on so I'd like to just figure out what is happening.

What is this match do method?

Jwan622
  • 11,015
  • 21
  • 88
  • 181
  • Can you clarify your question a bit? On the one hand, you ask about metaprogramming, but on the other hand, it also appears that you lack the basic fundamentals of Ruby syntax. So, what is your question exactly? Is it about RSpec Matchers? Is it about metaprogramming? (In which case it is probably a duplicate of a question that has already been asked and answered.) Is it about basic Ruby syntax? (In that case, it is *definitely* a dupilcate.) – Jörg W Mittag Oct 28 '16 at 16:15
  • Can you clarify what is going on here? – Jwan622 Oct 28 '16 at 16:30
  • The "section of code" you ask about isn't even syntactically valid Ruby. You need to clarify your question. Do you want an explanation of Ruby syntax? Of Ruby metaprogramming? Of RSpec? See http://meta.stackoverflow.com/q/253894/2988 and http://meta.stackoverflow.com/q/278797/2988 – Jörg W Mittag Oct 28 '16 at 16:42
  • But I copied it from the RSpec docs.... – Jwan622 Oct 28 '16 at 17:08

1 Answers1

1

You can look at the rspec source docs for starters - http://www.rubydoc.info/gems/rspec-expectations/RSpec/Matchers/DSL/Matcher

if you wanted to make a method callable like this:

some_method :symbol do
end

# one-liner version (parens are needed for arg)
some_method(:symbol) { }

you could define this:

def some_method(arg, &block)
  # the block gets called in here
end

See Blocks and yields in Ruby

As far as the symbol being turned into a method - this is actually pretty common, and is one of the main things that distinguishes symbols from strings.

So on that RSpec doc page, it says:

The block passed to RSpec::Matchers.define will be evaluated in the context of the singleton class of an instance, and will have the Macros methods available.

If you want to see exactly what's going on here you can go through the RSpec source code. However the internals aren't necessarily as well documented,

See What exactly is the singleton class in ruby?

Community
  • 1
  • 1
max pleaner
  • 26,189
  • 9
  • 66
  • 118