lib/trellis/trellis.rb in trellis-0.0.7 vs lib/trellis/trellis.rb in trellis-0.0.8

- old
+ new

@@ -61,10 +61,11 @@ def self.inherited(child) #:nodoc: child.class_attr_reader(:homepage) child.attr_array(:persistents) child.class_attr_reader(:session_config) child.attr_array(:static_routes) + child.attr_array(:routers) child.meta_def(:logger) { Application.logger } child.instance_variable_set(:@session_config, OpenStruct.new({:impl => :cookie})) super end @@ -146,15 +147,22 @@ self.class.static_routes.each do |path| application = Rack::Static.new(application, path) end application end + + def self.routers + unless @routers + @routers = Page.subclasses.values.collect { |page| page.router }.compact.sort {|a,b| b.score <=> a.score } + end + @routers + end # find the first page with a suitable router, if none is found use the default router def find_router_for(request) - match = Page.subclasses.values.find { |page| page.router && page.router.matches?(request) } - match ? match.router : DefaultRouter.new(:application => self) + match = Application.routers.find { |router| router.matches?(request) } + match || DefaultRouter.new(:application => self) end # rack call interface. def call(env) dup.call!(env) @@ -332,17 +340,22 @@ # -- Router -- # A Router returns a Route in response to an HTTP request class Router EVENT_REGEX = %r{^(?:.+)/events/(?:([^/\.]+)(?:\.([^/\.]+)?)?)(?:/(?:([^\.]+)?))?} - attr_reader :application, :pattern, :keys, :path, :page + attr_reader :application, :pattern, :keys, :path, :page, :score def initialize(options={}) @application = options[:application] @path = options[:path] @page = options[:page] - compile_path if @path + if @path + compile_path + compute_score + else + @score = 3 # since "/*" scores at 2 + end end def route(request = nil) # get the event information if any value, source, event = request.path_info.match(EVENT_REGEX).to_a.reverse if request @@ -374,10 +387,14 @@ end params << request.params params.each_pair { |name, value| page.instance_variable_set("@#{name}".to_sym, value) } end end + + def to_s + @path + end private # borrowed (stolen) from Sinatra! def compile_path @@ -404,9 +421,21 @@ elsif @path.respond_to? :match @pattern = path else raise TypeError, @path end + end + + def compute_score + score = 0 + parts = @path.split('/').delete_if {|part| part.empty? } + parts.each_index do |index| + part = parts[index] + power = parts.size - index + factor = part.match('\*') ? 1 : (part.match(':') ? 2 : 3) + score = score + (factor * (2**index)) + end + @score = score end end # -- DefaultRouter -- # The default routing scheme is in the form /page[.event[_source]][/value][?query_params]