Skip to content

Instantly share code, notes, and snippets.

@pjb3
Created January 3, 2012 00:38
Show Gist options
  • Save pjb3/1552851 to your computer and use it in GitHub Desktop.
Save pjb3/1552851 to your computer and use it in GitHub Desktop.
Use Ruby 1.9 Named Captures To Implement A Router
class Router
attr_accessor :routes
WILDCARD_PATTERN = /\/\*/
NAMED_SEGMENTS_PATTERN = /\/:([^$\/]+)/
NAMED_SEGMENTS_REPLACEMENT_PATTERN = /\/:([^$\/]+)/
def initialize(routes)
@routes = routes
end
def route(path)
routes.each do |route|
if route.first =~ WILDCARD_PATTERN
src = "\\A#{route.first.gsub('*','(.*)')}\\Z"
if match = path.match(Regexp.new(src))
return [route.last, match[1].split('/')]
end
elsif route.first =~ NAMED_SEGMENTS_PATTERN
src = "\\A#{route.first.gsub(NAMED_SEGMENTS_REPLACEMENT_PATTERN, '/(?<\1>[^$/]+)')}\\Z"
if match = path.match(Regexp.new(src))
return [route.last, Hash[match.names.zip(match.captures)]]
end
elsif path == route.first
return [route.last]
end
end
nil
end
end
require 'router'
describe Router do
it "should match using a literal string if route does not contain a '*'" do
router = Router.new([["/foo", 1], ["/bar", 2], ["/bark", 3]])
router.route("/foo").should == [1]
router.route("/bar").should == [2]
router.route("/bark").should == [3]
router.route("/fail").should be_nil
end
it "should match using a Regexp if the route contains a '*'" do
router = Router.new([["/foo", 1], ["/bar/*", 2], ["/bark", 3]])
router.route("/foo").should == [1]
router.route("/bar/").should == [2, []]
router.route("/bar").should be_nil
router.route("/bar/bang").should == [2, ["bang"]]
router.route("/bark").should == [3]
router.route("/fail").should be_nil
end
it "should match using a Regexp if the route contains named segments" do
router = Router.new([["/foo", 1], ["/foo/:name", 2], ["/foo/:name/:action", 3]])
router.route("/foo").should == [1]
router.route("/foo/bar").should == [2, { "name" => "bar" }]
router.route("/foo/bar/bang").should == [3, { "name" => "bar", "action" => "bang" }]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment