Skip to content

Instantly share code, notes, and snippets.

@F-3r
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save F-3r/06001b4b978585ad5538 to your computer and use it in GitHub Desktop.

Select an option

Save F-3r/06001b4b978585ad5538 to your computer and use it in GitHub Desktop.

Revisions

  1. F-3r revised this gist Jun 11, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion base.rb
    Original file line number Diff line number Diff line change
    @@ -55,7 +55,8 @@ def _call(env)
    @request = Hobbit::Request.new @env
    @response = Hobbit::Response.new

    catch(:response) { route_eval }
    response = catch(:response) { route_eval }
    response.finish
    end

    def halt(status = 200, headers = {}, body = [])
  2. F-3r created this gist Jun 11, 2014.
    97 changes: 97 additions & 0 deletions base.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    require 'forwardable'

    module Hobbit
    class Base
    class << self
    extend Forwardable

    def_delegators :stack, :map, :use

    %w(DELETE GET HEAD OPTIONS PATCH POST PUT).each do |verb|
    define_method(verb.downcase) { |path, &block| routes[verb] << compile_route(path, &block) }
    end

    alias :_new :new
    def new(*args, &block)
    stack.run _new(*args, &block)
    stack
    end

    def call(env)
    new.call env
    end

    def routes
    @routes ||= Hash.new { |hash, key| hash[key] = [] }
    end

    def stack
    @stack ||= Rack::Builder.new
    end

    private

    def compile_route(path, &block)
    route = { block: block, compiled_path: nil, extra_params: [], path: path }

    compiled_path = path.gsub(/:\w+/) do |match|
    route[:extra_params] << match.gsub(':', '').to_sym
    '([^/?#]+)'
    end
    route[:compiled_path] = /^#{compiled_path}$/

    route
    end
    end

    attr_reader :env, :request, :response

    def call(env)
    dup._call env
    end

    def _call(env)
    @env = env
    @request = Hobbit::Request.new @env
    @response = Hobbit::Response.new

    catch(:response) { route_eval }
    end

    def halt(status = 200, headers = {}, body = [])
    response.status = status
    response.headers.merge! headers
    response.body = body

    throw :response, response
    end

    private

    def route_eval
    route = find_route

    if route
    response.write(instance_eval(&route[:block]))
    throw :response, response
    else
    halt 404
    end
    end

    def find_route
    route = self.class.routes[request.request_method].detect do |r|
    r[:compiled_path] =~ request.path_info
    end

    if route
    $~.captures.each_with_index do |value, index|
    param = route[:extra_params][index]
    request.params[param] = value
    end
    end

    route
    end
    end
    end