Permalink
Browse files

make Sinatra::Delegator play nice with method_missing proxies, fixes #…

  • Loading branch information...
1 parent 1632f24 commit 53b5ccde480b13370c09879aa93c336e293a9887 @rkh rkh committed Apr 17, 2011
Showing with 65 additions and 1 deletion.
  1. +8 −0 lib/sinatra/base.rb
  2. +57 −1 test/delegator_test.rb
View
@@ -1490,6 +1490,14 @@ def self.delegate(*methods)
methods.each do |method_name|
eval <<-RUBY, binding, '(__DELEGATE__)', 1
def #{method_name}(*args, &b)
+ arity = ::Sinatra::Delegator.target.method(#{method_name.inspect}).arity
+ if arity < 0 ? args.size < -arity - 1 : args.size != arity
+ begin
+ return super
+ rescue NameError => e
+ raise e unless e.message.include? #{method_name.to_s.inspect}
+ end
+ end
::Sinatra::Delegator.target.send(#{method_name.inspect}, *args, &b)
end
private #{method_name.inspect}
View
@@ -1,6 +1,13 @@
class DelegatorTest < Test::Unit::TestCase
class Mirror
attr_reader :last_call
+
+ Sinatra::Delegator.private_instance_methods.each do |method|
+ define_method(method) do |*a, &b|
+ method_missing(method, *a, &b)
+ end
+ end
+
def method_missing(*a, &b)
@last_call = [*a.map(&:to_s)]
@last_call << b if b
@@ -100,13 +107,62 @@ def target
assert_equal app.last_call, ["helpers", mixin.to_s ]
end
-
it "registers helpers with the delegation target" do
app, mixin = mirror, Module.new
Sinatra.use mixin
assert_equal app.last_call, ["use", mixin.to_s ]
end
+ it "should work with method_missing proxies for options" do
+ mixin = Module.new do
+ def method_missing(method, *args, &block)
+ return super unless method.to_sym == :options
+ {:some => :option}
+ end
+ end
+
+ app = mirror
+ def app.options(arg, *rest) "yay" end
+
+ a = b = c = nil
+ delegate do
+ extend mixin
+ a, b, c = options, options(1), options(1, 2)
+ end
+
+ assert_equal({:some => :option}, a)
+ assert_equal("yay", b)
+ assert_equal("yay", c)
+ end
+
+ it "should work with method_missing proxies for methods arity > 0" do
+ mixin = Module.new do
+ def method_missing(method, *args, &block)
+ return super unless method.to_sym == :options
+ {:some => :option}
+ end
+ end
+
+ app = mirror
+ def app.options(arg) "yay" end
+
+ a = b = c = nil
+ delegate do
+ extend mixin
+ a, b, c = options, options(1), options(1, 2)
+ end
+
+ assert_equal({:some => :option}, a)
+ assert_equal("yay", b)
+ assert_equal({:some => :option}, c)
+ end
+
+ it "should not raise a NameError for methods not handled by a proxy" do
+ app = mirror
+ def app.options(arg) "yay" end
+ assert_raises(ArgumentError) { delegate { options }}
+ end
+
delegates 'get'
delegates 'patch'
delegates 'put'

0 comments on commit 53b5ccd

Please sign in to comment.