passing a block to #pass will not 404, but eval the block

This is huge for writing extensions that install routes.
The developer can set the block to do default behaviour
if the app that registered the extension has not, or does
not want to, customize the route.

example:

  # MyFooExt
  ...
  def self.registered(app)
    app.get "/foo" do
      do_foo_things
      pass do
        "You hit foo!"
      end
    end
  end

At this point, as the user of MyFooExt, I can let the default
behaviour happen or override:

  # MySinatraApp
  require 'sinatra/my_foo_ext'

  class MySinatraApp < Sinatra::Base
    register MyFooExt

    get "/foo" do
      # MyFooExt has done do_foo_things
      do_our_foo_things
      "All foo things done"
    end
  end
This commit is contained in:
Blake Mizerany 2009-12-09 22:11:02 -08:00
parent e14c700b18
commit e20797047d
2 changed files with 22 additions and 5 deletions

View File

@ -416,8 +416,8 @@ module Sinatra
# Pass control to the next matching route.
# If there are no more matching routes, Sinatra will
# return a 404 response.
def pass
throw :pass
def pass(&block)
throw :pass, block
end
# Forward the request to the downstream app -- middleware only.
@ -444,7 +444,7 @@ module Sinatra
end
# Run routes defined on the class and all superclasses.
def route!(base=self.class)
def route!(base=self.class, pass_block=nil)
if routes = base.routes[@request.request_method]
original_params = @params
path = unescape(@request.path_info)
@ -470,7 +470,7 @@ module Sinatra
@params = original_params.merge(params)
@block_params = values
catch(:pass) do
pass_block = catch(:pass) do
conditions.each { |cond|
throw :pass if instance_eval(&cond) == false }
route_eval(&block)
@ -483,10 +483,12 @@ module Sinatra
# Run routes defined in superclass.
if base.superclass.respond_to?(:routes)
route! base.superclass
route! base.superclass, pass_block
return
end
route_eval(&pass_block) if pass_block
route_missing
end

View File

@ -462,6 +462,21 @@ class RoutingTest < Test::Unit::TestCase
assert not_found?
end
it "uses optional block passed to pass as route block if no other route is found" do
mock_app {
get "/" do
pass do
"this"
end
"not this"
end
}
get "/"
assert ok?
assert "this", body
end
it "passes when matching condition returns false" do
mock_app {
condition { params[:foo] == 'bar' }