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]