Skip to content

Commit

Permalink
Fix matcher chaining to prevent name collisions.
Browse files Browse the repository at this point in the history
Previously, #chain used #define_method on the class to define an instance method on all instances.  We want it to define the method on only this instance, so we need to delegate to the singleton class instead (which the recently added #define_method does for us!).
  • Loading branch information
myronmarston authored and dchelimsky committed Oct 23, 2010
1 parent 32e3f9f commit 9c2971a
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
8 changes: 3 additions & 5 deletions lib/rspec/matchers/matcher.rb
Expand Up @@ -97,11 +97,9 @@ def diffable

# See RSpec::Matchers
def chain(method, &block)
self.class.class_eval do
define_method method do |*args|
block.call(*args)
self
end
define_method method do |*args|
block.call(*args)
self
end
end

Expand Down
8 changes: 8 additions & 0 deletions spec/rspec/matchers/matcher_spec.rb
Expand Up @@ -334,6 +334,14 @@ def assert_equal(a,b)
matcher.expecting('value').matches?('other value').should be_false
end

it "prevents name collisions on chainable methods from different matchers" do
m1 = RSpec::Matchers::Matcher.new(:m1) { chain(:foo) { raise "foo in m1" } }
m2 = RSpec::Matchers::Matcher.new(:m2) { chain(:foo) { raise "foo in m2" } }

expect { m1.foo }.to raise_error("foo in m1")
expect { m2.foo }.to raise_error("foo in m2")
end

context "defined using the dsl" do
def a_method_in_the_example
"method defined in the example"
Expand Down

0 comments on commit 9c2971a

Please sign in to comment.