Mark Needham

Thoughts on Software Development

Ruby: Using a variable in a regex

with one comment

We’re using Web Mock on my current project to stub out some of the external web requests in some of our integration tests and I managed to get myself very confused while trying to use a variable inside a regular expression that I was trying to pass to the ‘stub_request’ method.

The code was roughly like this:

some_url = "http://service.com/method"
 
stub_request(:any, /some_url/).
        to_return(:body => File.new('/path/to/some.xml'),
                                      :headers => {'Content-Length' => 666, 'Content-Type' => 'text/xml'},
                  :status => 200,
                  :headers => {'Content-Type' => 'text/xml'})

The request was being stubbed when I hard coded the url inside the regular expression but not being stubbed when I used the variable like in the example above.

I somehow missed the blindingly obvious in hindsight solution of treating variables inside a regular expression as if they were being used in a string.

If we wrap the variable inside ‘#{}’ then our problem is solved:

some_url = "http://service.com/method"
 
stub_request(:any, /#{some_url}/).
        to_return(:body => File.new('/path/to/some.xml'),
                                      :headers => {'Content-Length' => 666, 'Content-Type' => 'text/xml'},
                  :status => 200,
                  :headers => {'Content-Type' => 'text/xml'})

I still can’t quite believe I didn’t spot it straight away.

Written by Mark Needham

October 27th, 2010 at 1:55 pm

Posted in Ruby

Tagged with

  • http://twitter.com/rjhunter Rob Hunter

    Be careful with Ruby variables inside regular expressions.

    Consider the following code:
    expected_hostname = “b.com”
    actual_hostname.should =~ /#{expected_hostname}/

    This test will pass when actual_hostname is the plain string “b.com” but will also pass with all of the following:
    – “blockjabjab.com”
    – “b.com.au”
    – “becompletelyfree.co.uk”

    In the same way that you wouldn’t insert the string “Ben & Jerry” straight into an HTML document string, you are responsible for ensuring each layer is speaking the same language. In this case, it means either transforming the plain string into a regex (escaping) or accepting a regex component as the input.

    I hope this makes sense, I’m writing this on my phone and I can’t see all of what I’ve written.