Added route block params in routing statements [#140]

This commit is contained in:
Brandon Dimcheff 2009-01-28 15:27:32 -05:00 committed by Ryan Tomayko
parent 57183bc004
commit 6569d1b0fd
4 changed files with 122 additions and 1 deletions

View File

@ -50,6 +50,12 @@ Route patterns may include named parameters, accessible via the
"Hello #{params[:name]}!"
end
You can also access named parameters via block parameters:
get '/hello/:name' do |n|
"Hello #{n}!"
end
Route patterns may also include splat (or wildcard) parameters, accessible
via the <tt>params[:splat]</tt> array.
@ -69,6 +75,12 @@ Route matching with Regular Expressions:
"Hello, #{params[:captures].first}!"
end
Or with a block parameter:
get %r{/hello/([\w]+)} do |c|
"Hello, #{c}!"
end
Routes may include a variety of matching conditions, such as the user agent:
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do

View File

@ -377,6 +377,7 @@ module Sinatra
{}
end
@params = original_params.merge(params)
@block_params = values
catch(:pass) do
conditions.each { |cond|
@ -641,7 +642,7 @@ module Sinatra
define_method "#{verb} #{path}", &block
unbound_method = instance_method("#{verb} #{path}")
block = lambda { unbound_method.bind(self).call }
block = lambda { unbound_method.bind(self).call(*@block_params) }
(routes[verb] ||= []).
push([pattern, keys, conditions, block]).last

View File

@ -42,3 +42,11 @@ def describe(*args, &block)
end
klass.class_eval &block
end
# Do not output warnings for the duration of the block.
def silence_warnings
$VERBOSE, v = nil, $VERBOSE
yield
ensure
$VERBOSE = v
end

View File

@ -498,4 +498,104 @@ describe "Routing" do
assert ok?
assert_equal 'default', body
end
it 'passes a single url param as block parameters when one param is specified' do
mock_app {
get '/:foo' do |foo|
assert_equal 'bar', foo
end
}
get '/bar'
end
it 'passes multiple params as block parameters when many are specified' do
mock_app {
get '/:foo/:bar/:baz' do |foo, bar, baz|
assert_equal 'abc', foo
assert_equal 'def', bar
assert_equal 'ghi', baz
end
}
get '/abc/def/ghi'
end
it 'passes regular expression captures as block parameters' do
mock_app {
get(/^\/fo(.*)\/ba(.*)/) do |foo, bar|
assert_equal 'orooomma', foo
assert_equal 'f', bar
end
}
get '/foorooomma/baf'
end
it "supports mixing multiple splat params like /*/foo/*/* as block parameters" do
mock_app {
get '/*/foo/*/*' do |foo, bar, baz|
assert_equal 'bar', foo
assert_equal 'bling', bar
assert_equal 'baz/boom', baz
end
}
get '/bar/foo/bling/baz/boom'
end
it 'raises an ArgumentError if there are too few block parameters' do
mock_app {
get '/:foo/:bar/:baz' do |foo, bar|
'quux'
end
}
assert_raise(ArgumentError) { get '/a/b/c' }
end
it 'does not raise an ArgumentError with fewer block params defined then given in route' do
mock_app {
get '/:foo/:bar/:baz' do |foo|
'quux'
end
}
silence_warnings do
assert_nothing_raised { get '/a/b/c' }
end
end
it 'raises an ArgumentError with more block params defined then given' do
mock_app {
get '/:foo/:bar' do |foo, bar, baz|
'quux'
end
}
assert_raise(ArgumentError) { get '/a/b' }
end
it 'raises an ArgumentError if there are too many block parameters when there are no captures' do
mock_app {
get '/foo' do |foo|
'quux'
end
}
silence_warnings do
assert_nothing_raised { get '/foo' }
end
end
it 'succeeds if no block parameters are specified' do
mock_app {
get '/:foo/:bar' do
'quux'
end
}
assert_nothing_raised { get '/a/b' }
assert_equal 'quux', body
end
end