34

I have a Ruby Sinatra app and I have some code which I need to execute on all routes except for a few exceptions. How do I do this?

If I wanted to execute the code on selected routes (whitelist style) I'd do this:

['/join', "/join/*", "/payment/*"].each do |path|
    before path do
        #some code
    end
end

How do I do it the other way round though (blacklist style)? I want to match all routes except '/join', '/join/*' and '/payment/*'

lmirosevic
  • 15,787
  • 13
  • 70
  • 116

3 Answers3

43

With negative look-ahead:

before /^(?!\/(join|payment))/ do
  # ...
end

With pass:

 before do
   pass if %w[join payment].include? request.path_info.split('/')[1]
   # ...
 end

Or you could create a custom matcher.

Konstantin Haase
  • 25,687
  • 2
  • 57
  • 59
  • how can I include the root path ('/') in this pass statement? – Marcio Toshio Apr 29 '14 at 18:31
  • 1
    pass if ['join', 'payment', nil].include? request.path_info.split('/')[1] – Konstantin Haase May 06 '14 at 15:31
  • The pass works well for me but the negative look-ahead does not. Two problems: 1) Sinatra (1.4.6 at least) has a parsing error with a ^ character in a regular expression and 2) the negative look-ahead syntax only checks for the escaped forward-slash. Variable-width values aren't allowed. https://rubular.com/r/HEWorY6OFU5W9S – mrturtle Jan 29 '19 at 18:15
4

What I did to make a "before all, except..." filter is use a splat, and then run code on splat conditions.

before '/*' do
  unless params[:splat] == 'nofilter' || params[:splat] == 'beta'
    redirect '/beta'
  end
end

This allowed me to make a before filter with a redirect that didn't create a redirect loop

OneChillDude
  • 7,856
  • 10
  • 40
  • 79
1

You can use Regular Expressions for routing in sinatra

for example:

get %r{/hello/([\w]+)} do |c|
   "Hello, #{c}!"
end

taken from here. there you can find further informations.

to build and test your regex you can use http://rubular.com/

ben
  • 1,819
  • 15
  • 25
  • See, that's already clear from reading the docs. What's not clear from the docs (Sinatra: README) is whether or not *before filters* can also take regex patterns. You'll notice how *before and after filters* are in an entirely different section of the article to which you linked. So your answer adds no value (except perhaps that last link) and merely repeats what the docs already state. Thus my downvote. – 0xC0000022L Jun 02 '16 at 22:29