Created
April 20, 2010 00:23
-
-
Save juliocesar/371842 to your computer and use it in GitHub Desktop.
Simple object regex method router
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# >> class MyClass; include RegexRouter; end | |
# => MyClass | |
# >> obj = MyClass.new | |
# => #<MyClass:0x101859100 @routes={}> | |
# >> obj[%r(/words/(\w+))] = lambda do |word| puts "Found: #{word}" end | |
# => #<Proc:0x000000010184bb40@(irb):3> | |
# >> obj.go '/words/boo' | |
# Found: boo | |
# => nil | |
module RegexRouter | |
def self.included(base) | |
base.class_eval do | |
def initialize(*args, &block) | |
@routes = {} | |
super(*args, &block) | |
end | |
end | |
end | |
def []=(*args) | |
@routes.send :[]=, *(args.map { |arg| arg.is_a?(String) ? Regexp.new(arg) : arg }) | |
end | |
def go(route) | |
@routes.each do |regex, block| | |
if match = regex.match(route) | |
return (match.captures.any? ? block.call(*match.captures) : block.call) | |
end | |
end | |
raise NoMethodError, "Route not found: #{route}" | |
end | |
def routes | |
@routes | |
end | |
def @routes.count | |
@routes.keys.length | |
end | |
end | |
if $0 =~ /spec/ | |
require 'rubygems' | |
gem 'rspec', '>= 1.3.0'; require 'spec' | |
describe RegexRouter do | |
before do | |
class MyClass | |
include RegexRouter | |
end | |
@instance = MyClass.new | |
end | |
context 'methods' do | |
subject { @instance } | |
it { should respond_to :[]= } | |
it { should respond_to :routes } | |
it { subject.routes.should respond_to(:count) } | |
end | |
it 'works by passing a regex to [] and a block increments the route count by 1' do | |
@instance[/boo/] = lambda do 'omg' end | |
@instance.routes.count.should == 1 | |
end | |
context 'dispatching routes' do | |
it 'dispatches a method associated with a route when the param matches' do | |
jug = 'empty' | |
@instance[/foo/] = lambda do jug = 'water' end | |
@instance.go 'foo' | |
jug.should == 'water' | |
end | |
it "uses regex captures as arguments for a route's block" do | |
book = nil | |
@instance[%r(/books/(\d))] = lambda do |book_id| | |
book = book_id | |
end | |
@instance.go '/books/1' | |
book.should == '1' | |
end | |
end | |
it 'raises a NoMethodError when dispatching to a non-existent route' do | |
lambda do | |
@instance.go 'zomg' | |
end.should raise_error(NoMethodError) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment