module CustomMatchers
class Match < RSpec::Matchers::BuiltIn::Match
def matches?(actual)
# first ensure the regex matched
return false unless result = super
# only continue if specifying captures
return result unless expected_captures = @captures
actual_captures = to_hash result
RSpec::Matchers::BuiltIn::Include.new(expected_captures).matches?(actual_captures).tap do |captures_matched|
# replace expected/actual regex with the matchdata
# if the matchdata didn't match. this way we get a diff of the matchdata hashes
# otherwise, leave untouched so the description is per normal
unless captures_matched
@expected = expected_captures
@actual = actual_captures
end
end
end
def capturing(captures)
@captures = captures
self
end
private
def to_hash(matchdata)
Hash[matchdata.names.map(&:to_sym).zip matchdata.captures]
end
end
def matchy(expected)
Match.new expected
end
end