Class: Racket::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/racket/router.rb

Overview

Handles routing in Racket applications.

Instance Method Summary collapse

Constructor Details

#initializeRouter

Returns a new instance of Router.



26
27
28
29
30
# File 'lib/racket/router.rb', line 26

def initialize
  @router = HttpRouter.new
  @routes_by_controller = {}
  @actions_by_controller = {}
end

Instance Method Details

#cache_actions(controller) ⇒ nil

Caches available actions for each controller class. This also works for controller classes that inherit from other controller classes.

Parameters:

  • controller (Class)

Returns:

  • (nil)


37
38
39
40
41
42
43
44
45
46
# File 'lib/racket/router.rb', line 37

def cache_actions(controller)
  actions = Set.new
  current = controller
  while current < Controller
    actions.merge(current.instance_methods(false))
    current = current.superclass
  end
  @actions_by_controller[controller] = actions.to_a
  nil
end

#get_route(controller, action, params) ⇒ String

Returns a route to the specified controller/action/parameter combination.

Parameters:

  • controller (Class)
  • action (Symbol)
  • params (Array)

Returns:

  • (String)


54
55
56
57
58
59
60
61
62
# File 'lib/racket/router.rb', line 54

def get_route(controller, action, params)
  route = ''
  route << @routes_by_controller[controller] if @routes_by_controller.key?(controller)
  action = action.to_s
  route << "/#{action}" unless action.empty?
  route << "/#{params.join('/')}" unless params.empty?
  route = route[1..-1] if route.start_with?('//') # Special case for root path
  route
end

#map(path, controller) ⇒ nil

Maps a controller to the specified path.

Parameters:

  • path (String)
  • controller (Class)

Returns:

  • (nil)


69
70
71
72
73
74
75
76
# File 'lib/racket/router.rb', line 69

def map(path, controller)
  controller_base_path = path.empty? ? '/' : path
  Application.inform_dev("Mapping #{controller} to #{controller_base_path}.")
  @router.add("#{path}(/*params)").to(controller)
  @routes_by_controller[controller] = controller_base_path
  cache_actions(controller)
  nil
end

#render_error(status, error = nil) ⇒ Object

@todo: Allow the user to set custom handlers for different errors



79
80
81
82
83
84
85
86
87
# File 'lib/racket/router.rb', line 79

def render_error(status, error = nil)
  # If running in dev mode, let Rack::ShowExceptions handle the error.
  raise error if error && Application.dev_mode?

  # Not running in dev mode, let us handle the error ourselves.
  response = Response.new([], status, { 'Content-Type' => 'text/plain' })
  response.write("#{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}")
  response.finish
end

#route(env) ⇒ Array

Routes a request and renders it.

Parameters:

  • env (Hash)

    Rack environment

Returns:

  • (Array)

    A Rack response triplet



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/racket/router.rb', line 93

def route(env)
  begin
    catch :response do # Catches early exits from Controller.respond.
      # Find controller in map
      # If controller exists, call it
      # Otherwise, send a 404
      matching_routes = @router.recognize(env)
      unless matching_routes.first.nil?
        target_klass = matching_routes.first.first.route.dest
        params = matching_routes.first.first.param_values.first.reject { |e| e.empty? }
        action = params.empty? ? target_klass.get_option(:default_action) : params.shift.to_sym

        # Check if action is available on target
        return render_error(404) unless @actions_by_controller[target_klass].include?(action)

        # Initialize target
        target = target_klass.new
        # @fixme: File.dirname should not be used on urls!
        1.upto(params.count) do
          env['PATH_INFO'] = File.dirname(env['PATH_INFO'])
        end
        target.extend(Current.init(env, action, params))
        target.render(action)
      else
        render_error(404)
      end
    end
  rescue => err
    render_error(500, err)
  end
end