Permalink
Browse files

Delegate Matcher#define_method to its singleton class.

This allows you to define helper methods in a matcher using #define_method to gain access to the parameters.

- Closes #29.
  • Loading branch information...
myronmarston authored and dchelimsky committed Oct 9, 2010
1 parent 0d69b6f commit 8ece37a9653bfb84bc11c8eeab55b21923808580
Showing with 43 additions and 2 deletions.
  1. +25 −0 features/matchers/define_matcher.feature
  2. +10 −2 lib/rspec/matchers/matcher.rb
  3. +8 −0 spec/rspec/matchers/matcher_spec.rb
@@ -284,3 +284,28 @@ Feature: define matcher
| 4 examples, 2 failures |
| expected [1, 2, 3] to contain 1 and 4 |
| expected [1, 2, 3] not to contain 1 and 4 |
+
+ Scenario: use define_method to create a helper method with access to matcher params
+ Given a file named "define_method_spec.rb" with:
+ """
+ RSpec::Matchers.define :be_a_multiple_of do |expected|
+ define_method :is_multiple? do |actual|
+ actual % expected == 0
+ end
+ match { |actual| is_multiple?(actual) }
+ end
+
+ describe 9 do
+ it { should be_a_multiple_of(3) }
+ it { should_not be_a_multiple_of(4) }
+
+ # deliberate failures
+ it { should be_a_multiple_of(2) }
+ it { should_not be_a_multiple_of(3) }
+ end
+ """
+ When I run "rspec define_method_spec.rb"
+ Then the output should contain all of these:
+ | 4 examples, 2 failures |
+ | expected 9 to be a multiple of 2 |
+ | expected 9 not to be a multiple of 3 |
@@ -49,6 +49,10 @@ def does_not_match?(actual)
!matches?(actual)
end
+ def define_method(name, &block)
+ singleton_class.__send__(:define_method, name, &block)
+ end
+
# See RSpec::Matchers
def match(&block)
@match_block = block
@@ -124,8 +128,7 @@ def making_declared_methods_public # :nodoc:
# cause features to fail and that will make users unhappy. So don't.
orig_private_methods = private_methods
yield
- st = (class << self; self; end)
- (private_methods - orig_private_methods).each {|m| st.__send__ :public, m}
+ (private_methods - orig_private_methods).each {|m| singleton_class.__send__ :public, m}
end
def cache_or_call_cached(key, &block)
@@ -148,6 +151,11 @@ def expected_to_sentence
to_sentence(@expected)
end
+ unless method_defined?(:singleton_class)
+ def singleton_class
+ class << self; self; end
+ end
+ end
end
end
end
@@ -58,6 +58,14 @@ module Matchers
end
end
+ it "allows helper methods to be defined with #define_method to have access to matcher parameters" do
+ matcher = RSpec::Matchers::Matcher.new(:name, 3, 4) do |a, b|
+ define_method(:sum) { a + b }
+ end
+
+ matcher.sum.should == 7
+ end
+
it "is not diffable by default" do
matcher = RSpec::Matchers::Matcher.new(:name) {}
matcher.should_not be_diffable

0 comments on commit 8ece37a

Please sign in to comment.