1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00

Fix block param arity handling under 1.9

This modifies the way block params are handled so that block params
have 1.8 semantics under 1.8 and 1.9 semantics under 1.9.

* Spec Ruby 1.9 such that mismatched arity raises an ArgumentError.

* Spec Ruby 1.8 such that mismatched arity does not raise an
  ArgumentError.

* Do not attempt to pass block params to handlers defined with 0
  arity. This avoids the ArgumentError for 0 arity blocks on 1.9
  with the common case route that defines no block params but does
  include parameter captures/splats.

Coding for Ruby 1.9 results in code that is compatible with both
versions.
This commit is contained in:
Ryan Tomayko 2009-02-02 00:18:43 -08:00
parent f497f4f36f
commit dfcb252773
2 changed files with 81 additions and 28 deletions

View file

@ -638,7 +638,12 @@ module Sinatra
define_method "#{verb} #{path}", &block
unbound_method = instance_method("#{verb} #{path}")
block = lambda { unbound_method.bind(self).call(*@block_params) }
block =
if block.arity != 0
lambda { unbound_method.bind(self).call(*@block_params) }
else
lambda { unbound_method.bind(self).call }
end
(routes[verb] ||= []).
push([pattern, keys, conditions, block]).last

View file

@ -528,11 +528,13 @@ describe "Routing" do
get(/^\/fo(.*)\/ba(.*)/) do |foo, bar|
assert_equal 'orooomma', foo
assert_equal 'f', bar
'looks good'
end
}
get '/foorooomma/baf'
assert ok?
assert_equal 'looks good', body
end
it "supports mixing multiple splat params like /*/foo/*/* as block parameters" do
@ -541,14 +543,16 @@ describe "Routing" do
assert_equal 'bar', foo
assert_equal 'bling', bar
assert_equal 'baz/boom', baz
'looks good'
end
}
get '/bar/foo/bling/baz/boom'
assert ok?
assert_equal 'looks good', body
end
it 'raises an ArgumentError if there are too few block parameters' do
it 'raises an ArgumentError with block arity > 1 and too many values' do
mock_app {
get '/:foo/:bar/:baz' do |foo, bar|
'quux'
@ -558,19 +562,7 @@ describe "Routing" do
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
it 'raises an ArgumentError with block param arity > 1 and too few values' do
mock_app {
get '/:foo/:bar' do |foo, bar, baz|
'quux'
@ -580,18 +572,6 @@ describe "Routing" do
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
@ -599,7 +579,75 @@ describe "Routing" do
end
}
assert_nothing_raised { get '/a/b' }
get '/a/b'
assert ok?
assert_equal 'quux', body
end
it 'passes all params with block param arity -1 (splat args)' do
mock_app {
get '/:foo/:bar' do |*args|
args.join
end
}
get '/a/b'
assert ok?
assert_equal 'ab', body
end
# NOTE Block params behaves differently under 1.8 and 1.9. Under 1.8, block
# param arity is lax: declaring a mismatched number of block params results
# in a warning. Under 1.9, block param arity is strict: mismatched block
# arity raises an ArgumentError.
if RUBY_VERSION >= '1.9'
it 'raises an ArgumentError with block param arity 1 and no values' do
mock_app {
get '/foo' do |foo|
'quux'
end
}
assert_raise(ArgumentError) { get '/foo' }
end
it 'does not raise an ArgumentError with block param arity 1 and too many values' do
mock_app {
get '/:foo/:bar/:baz' do |foo|
'quux'
end
}
assert_raise { get '/a/b/c' }
end
else
it 'does not raise an ArgumentError with block param arity 1 and no values' do
mock_app {
get '/foo' do |foo|
'quux'
end
}
silence_warnings { get '/foo' }
assert ok?
assert_equal 'quux', body
end
it 'does not raise an ArgumentError with block param arity 1 and too many values' do
mock_app {
get '/:foo/:bar/:baz' do |foo|
'quux'
end
}
silence_warnings { get '/a/b/c' }
assert ok?
assert_equal 'quux', body
end
end
end