class RackDispatch::Application

Public Class Methods

as(role) { || ... } click to toggle source
# File lib/rack_dispatch/application.rb, line 3
def self.as(role)
  _previous_role = @role ; @role = role ; yield ; @role = _previous_role
end
route(method, path, with: {}, thereupon: nil, redirect: nil, template: nil) click to toggle source
# File lib/rack_dispatch/application.rb, line 7
def self.route(method, path, with: {}, thereupon: nil, redirect: nil, template: nil)
  builders = []
  handlers = {}

  pattern_scan = path.scan(/(\:([a-z_]+))/).flatten.map do |value|
    if value.match(':')
      value
    else
      builder_class = Object.const_get("#{value}_builder".split('_').map(&:capitalize).join)
      builders << builder_class.new
      builder_class.regexp
    end
  end

  pattern_keys = pattern_scan.select.with_index { |_, i| i.even? }
  pattern = /\A#{path.gsub(Regexp.union(pattern_keys), Hash[*pattern_scan])}\z/

  with.each do |handler_name, condition|
    handler = Object.const_get("#{handler_name}_handler".split('_').map(&:capitalize).join).new
    handlers[handler] = condition
  end

  tasks = Array(thereupon).map do |task_name|
    Object.const_get("#{task_name}_task".split('_').map(&:capitalize).join).new
  end

  destination = template ? TemplateDestination.new(template) : RedirectDestination.new(redirect)

  ((@routes ||= {})[method.to_s.downcase] ||= []) << [pattern, builders, handlers, tasks, destination]
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack_dispatch/application.rb, line 38
def call(env)
  request = Rack::Request.new(env)
  response = Rack::Response.new
  computed_handlers = {}

  routes = self.class.instance_variable_get(:@routes)[request.request_method.downcase].select do |pattern, builders, handlers, tasks, destination|
    pattern.match(request.path) do |matches|
      # user matching

      builders.zip(matches[1..-1]).all? do |builder, value|
        builder_name = builder.class.name.sub(/Builder\z/, '').gsub(/(.)([A-Z])/,'\1_\2').downcase

        if request.params[builder_name]
          true
        elsif result = builder.call(value)
          request.update_param(builder_name, result) ; true
        end
      end
    end
  end

  route = routes.find do |pattern, builders, handlers, tasks, destination|
    handlers.all? do |handler, condition|
      (computed_handlers.key?(handler) && computed_handlers[handler] == condition) ||
        ((computed_handlers[handler] = handler.call(request)) == condition)
    end
  end

  if route
    route[3].each do |task|
      task.call(response)
    end

    route.last.call(request, response)
  else
    response.status = 404
    response.write 'Not Found'
  end

  response.finish
end