On Feb 8, 2011, at 4:14 AM, Matt Wynne wrote: > > On 4 Feb 2011, at 09:30, Alan B wrote: > >> Hi all, I'm trying to create a custom matcher that will visit a given >> path and check it's authenticated. >> Here's what I have so far (using rspec-rails and capybara): >> >> matcher :require_authentication do >> match do |path| >> visit path >> #page.current_path.should == sign_in_path >> page.current_path.should == '/sign_in' >> end >> end >> >> The above version works, but when using the commented out line I get: >> >> NameError: >> undefined local variable or method `sign_in_path' for >> #<RSpec::Matchers::Matcher:0xbbd68ec> >> >> sign_in_path is one of the routes in my application and works fine >> inside a describe/it block. >> I don't understand why the matcher recognises visit() but not >> sign_in_path. > > I'm surprised either of them do.
Actually, I'm not, but that's because I know something that you don't know (because I wrote it and it's not well documented): <background> A matcher created using the Matcher DSL is provided access to the example it is running in. When it receives method_missing, it asks the example if _it_ will respond to the message and, if so, sends it to the example. </background> <educated_guess guarantees="none"> If visit() is defined in the scope of the example using "def visit", then example.respond_to?(:visit) would return true, so the matcher would send visit() to the example. If, however, sign_in_path() is handled with method_missing(), but respond_to?() is not also overridden to return true for respond_to?(:sign_in_path), then the matcher would call super from method_missing, raising the NameError. You can test this theory out by putting the following in the same example before the matcher: self.should respond_to(:visit) self.should respond_to(:sign_in_path) If my guess is correct, the former will pass, but the latter will fail. If they both pass, then I'm not sure about the explanation. </educated_guess> HTH, David > This DSL is just a factory method for a matcher class. Unless that matcher > class includes Capybara and the Rails routing methods module (can't remember > the name off-hand) you won't have access to either of these methods in the > matcher. Look at the non-DSL way to create a matcher and this will make more > sense. > > Also, you need to return true / false from #match, rather than using an > assertion. > > cheers, > Matt > > m...@mattwynne.net > 07974 430184 > > _______________________________________________ > rspec-users mailing list > rspec-users@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users Cheers, David _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users