Skip to content

Instantly share code, notes, and snippets.

@shanna
Created February 23, 2011 09:46
Show Gist options
  • Save shanna/840227 to your computer and use it in GitHub Desktop.
Save shanna/840227 to your computer and use it in GitHub Desktop.
Sinatra routing inconsistency.
sinatra/master:
route | request | params
---------------------------------------------+----------+---------------------------
'/*' | /foo | {splat: ['foo']}
'/:splat' | /foo | {splat: ['foo']}
'/:bampf' | /foo | {bampf: 'foo'}
%r{^/(?<splat>[^/?#]+)/?$} | /foo | {splat: ['foo']}
%r{^/(?<bampf>[^/?#]+)/?$} | /foo | {bampf: 'foo'}
'/*/*' | /foo/bar | {splat: ['foo', 'bar']}
'/:splat/:splat' | /foo/bar | {splat: ['foo', 'bar']}
'/:bampf/:bampf' | /foo/bar | {bampf: 'bar'}
%r{^/(?<splat>[^/?#]+)/(?<splat>[^/?#]+)/?$} | /foo/bar | {splat: ['foo']}
%r{^/(?<bampf>[^/?#]+)/(?<bampf>[^/?#]+)/?$} | /foo/bar | {bampf: 'foo'}
* Splat is a special case not an alias.
* Named routes perform differently to single splat or named regexp group.
* Duplicate variable paths behave differently depending on if you use '*' splat, a named route or a named regexp group.
shanna/named_capture_routing: (1.9 only because we moved on from 1.8 a long time ago)
route | request | params
---------------------------------------------+----------+---------------------------
'/*' | /foo | {splat: 'foo'}
'/:splat' | /foo | {splat: 'foo'}
'/:bampf' | /foo | {bampf: 'foo'}
%r{^/(?<splat>[^/?#]+)/?$} | /foo | {splat: 'foo'}
%r{^/(?<bampf>[^/?#]+)/?$} | /foo | {bampf: 'foo'}
'/*/*' | /foo/bar | {splat: ['foo', 'bar']}
'/:splat/:splat' | /foo/bar | {splat: ['foo', 'bar']}
'/:bampf/:bampf' | /foo/bar | {bampf: ['foo', 'bar']}
%r{^/(?<splat>[^/?#]+)/(?<splat>[^/?#]+)/?$} | /foo/bar | {splat: ['foo', 'bar']}
%r{^/(?<bampf>[^/?#]+)/(?<bampf>[^/?#]+)/?$} | /foo/bar | {bampf: ['foo', 'bar']}
* Splat '*' is an alias for :splat which itself is an alias for (?<splat>[^/?#]+)
* Duplicate named variable paths always return an array.
* Single named variables return scalar.
  • Original patch (no longer around) patching the inconsistency wasn’t deemed an API change not a bug in the lighthouse ticket and rejected.

  • Depending on oniguruma regexp removes a bunch of code. Legacy 1.8 users would need oniguruma which apparently isn’t an option because of people unlucky enough to be dealing with JRuby.

  • I was too lazy to both keep the inconsistency and support named groups properly while providing backwards compatibility for 1.8 users so I gave up and we run a fork.

  • I’ve been waiting for a major version bump (hence the tweet) to be in the works to satisfy semantic versioning since whoever rejected the ticket doesn’t think it’s a bug.

@shanna
Copy link
Author

shanna commented Feb 23, 2011

Oh. And creating a token like:

(?<bampf>[^/?#]+){0} \g<bampf>/\g<bampf>

Doesn't work in either version because the named_captures method in Regexp only returns the first position. Is this a bug or don't I quite understand the named capture groups?

@rkh
Copy link

rkh commented Feb 23, 2011

Issue is: all code using splat would always have to check whether it's an array or a string.

@shanna
Copy link
Author

shanna commented Feb 23, 2011

Chances are you wrote the route in the first place though and the params[] handling is roughly a couple lines below that route definition. Splat, named param syntax or regexp it doesn't matter anymore this way. At least thats what we found in practice :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment