Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added route block params in routing statements [#140]

  • Loading branch information...
commit 6569d1b0fd483f44e37fe0d7f56e394deb3e579e 1 parent 57183bc
@bdimcheff bdimcheff authored rtomayko committed
View
12 README.rdoc
@@ -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
3  lib/sinatra/base.rb
@@ -377,6 +377,7 @@ def route!
{}
end
@params = original_params.merge(params)
+ @block_params = values
catch(:pass) do
conditions.each { |cond|
@@ -641,7 +642,7 @@ def route(verb, path, opts={}, &block)
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
8 test/helper.rb
@@ -42,3 +42,11 @@ def self.after(&block) define_method(:teardown, &block) end
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
100 test/routing_test.rb
@@ -498,4 +498,104 @@ def route_def(pattern)
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
Please sign in to comment.
Something went wrong with that request. Please try again.