From 8b8ddfef56bf4137076f9f4ceab56e14ce0a0288 Mon Sep 17 00:00:00 2001 From: Blake Mizerany Date: Mon, 9 Mar 2009 21:45:47 -0700 Subject: [PATCH] Hook mechanizm for route_added [help from rtomayko] Example: module Sinatra module RouteAddedExtSample def self.route_added(verb, path) p [verb, path] end end register RouteAddedExtSample end post '/' do do_something 'ok' end Output: ["POST", "/"] move superclass logic into extensions attr reader --- lib/sinatra/base.rb | 13 ++++++++++ test/route_added_hook_test.rb | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 test/route_added_hook_test.rb diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb index c30e8dfd..68d2273a 100644 --- a/lib/sinatra/base.rb +++ b/lib/sinatra/base.rb @@ -553,6 +553,7 @@ module Sinatra @middleware = [] @errors = {} @prototype = nil + @extensions = [] class << self attr_accessor :routes, :filters, :conditions, :templates, @@ -698,10 +699,16 @@ module Sinatra lambda { unbound_method.bind(self).call } end + invoke_hook(:route_added, verb, path) + (routes[verb] ||= []). push([pattern, keys, conditions, block]).last end + def invoke_hook(name, *args) + extensions.each { |e| e.send(name, *args) if e.respond_to?(name) } + end + def compile(path) keys = [] if path.respond_to? :to_str @@ -733,8 +740,13 @@ module Sinatra include *extensions if extensions.any? end + def extensions + (@extensions + (superclass.extensions rescue [])).uniq + end + def register(*extensions, &block) extensions << Module.new(&block) if block_given? + @extensions += extensions extensions.each do |extension| extend extension extension.registered(self) if extension.respond_to?(:registered) @@ -817,6 +829,7 @@ module Sinatra @errors = base.errors.dup @middleware = base.middleware.dup @prototype = nil + @extensions = [] end protected diff --git a/test/route_added_hook_test.rb b/test/route_added_hook_test.rb new file mode 100644 index 00000000..429e04a3 --- /dev/null +++ b/test/route_added_hook_test.rb @@ -0,0 +1,47 @@ +require File.dirname(__FILE__) + '/helper' + +module RouteAddedTest + @routes = [] + def self.routes ; @routes ; end + def self.route_added(verb, path) + @routes << [verb, path] + end +end + +describe "route_added Hook" do + + before { RouteAddedTest.routes.clear } + + it "should be notified of an added route" do + mock_app(Class.new(Sinatra::Base)) { + register RouteAddedTest + get('/') {} + } + + assert_equal [["GET", "/"], ["HEAD", "/"]], + RouteAddedTest.routes + end + + it "should include hooks from superclass" do + a = Class.new(Class.new(Sinatra::Base)) + b = Class.new(a) + + a.register RouteAddedTest + b.class_eval { post("/sub_app_route") {} } + + assert_equal [["POST", "/sub_app_route"]], + RouteAddedTest.routes + end + + it "should only run once per extension" do + mock_app(Class.new(Sinatra::Base)) { + register RouteAddedTest + register RouteAddedTest + get('/') {} + } + + assert_equal [["GET", "/"], ["HEAD", "/"]], + RouteAddedTest.routes + end + +end