Class: Mack::Application

Inherits:
Object show all
Includes:
Extlib::Hook, Routes::Urls
Defined in:
lib/mack/application.rb

Overview

This is the heart and soul of the Mack framework! This class interfaces with the Rack framework. It handles all the dispatching back and forth between the Rack framework and a Mack application.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Routes::Urls

create_method, #redirect_html, #url_for_pattern

Instance Attribute Details

#cookiesObject (readonly)

:nodoc:



11
12
13
# File 'lib/mack/application.rb', line 11

def cookies
  @cookies
end

#original_actionObject (readonly)

Returns the value of attribute original_action.



14
15
16
# File 'lib/mack/application.rb', line 14

def original_action
  @original_action
end

#original_controllerObject (readonly)

Returns the value of attribute original_controller.



13
14
15
# File 'lib/mack/application.rb', line 13

def original_controller
  @original_controller
end

#requestObject (readonly)

:nodoc:



10
11
12
# File 'lib/mack/application.rb', line 10

def request
  @request
end

#responseObject (readonly)

:nodoc:



9
10
11
# File 'lib/mack/application.rb', line 9

def response
  @response
end

#runner_helpersObject (readonly)

:nodoc:



12
13
14
# File 'lib/mack/application.rb', line 12

def runner_helpers
  @runner_helpers
end

Instance Method Details

#call(env) ⇒ Object

This method needs to be defined as part of the Rack framework. As is noted for the Mack::Runner class, this is where the center of the Mack framework lies.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/mack/application.rb', line 18

def call(env)
  env["rack.errors"] = StringIO.new # Send Rack errors nowhere fast!
  begin
    setup(env)
    begin
      route = Mack::Routes.retrieve(self.request)
      if route[:redirect_to]
        # because the route is specified to be a redirect, let's do that:
        redirect_to(route)
      else
        # set these in case we need them for handling errors:
        @original_controller = route[:controller]
        @original_action = route[:action]
        run_controller(route)
      end
      # return teardown
    rescue Exception => e
      # There was an exception, let's see if there's a handler for this error in routes:
      route = Mack::Routes.retrieve_from_error(e.class)
      unless route.nil?
        self.request.params[:original_controller] = @original_controller
        self.request.params[:original_action] = @original_action
        # There is a handler, let's try running that:
        run_controller(route, e)
      else
        # If we can't find the resource, or there's no route, let's check the public directory:
        case e
        when Mack::Errors::ResourceNotFound, Mack::Errors::UndefinedRoute
          return try_to_find_resource(env, e)
        else
          # Re-raise the exception
          raise e
        end
      end
      # return teardown
    end
  # Capture all the Exceptions for this call:
  rescue Exception => e
    Mack.logger.error e
    case e
    when Mack::Errors::ResourceNotFound, Mack::Errors::UndefinedRoute
      handle_error(404, 'Page Not Found!', e)
    # If it's any other type of exception render the 500.html page:
    else
      handle_error(500, 'Server Error!', e)
    end
    # return teardown
  ensure
    teardown
  end
  return self.response.finish
end

#redirect_to(route) ⇒ Object

This will redirect the request to the specified url. A default status of 302, Moved Temporarily, is set if no status is specified. A simple HTML page is rendered in case the redirect does not occur.



137
138
139
140
141
142
143
144
145
146
147
# File 'lib/mack/application.rb', line 137

def redirect_to(route)
  status = route[:status] || 302
  url = route[:redirect_to]
  options = self.request.params
  options.merge!(route)
  options - [:controller, :action, :redirect_to, :method, :status, :format]
  url = url_for_pattern(url, options)
  self.response.status = status
  self.response['Location'] = url
  self.response.write(redirect_html(self.request.path_info, url, status))
end

#run_controller(route, e = nil) ⇒ Object

private



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/mack/application.rb', line 72

def run_controller(route, e = nil)
  runner_block = route[:runner_block]
  route - :runner_block
  
  self.request.params = self.request.params.merge(route)
  self.response.content_type = Mack::Utils::MimeTypes[self.request.params[:format]]
  catch(:finished) do
    if runner_block
      runner_block.call(self.request, self.response, self.cookies)
    end
  
    # let's handle a normal request:
    begin
      cont = "#{route[:controller].to_s.camelcase}Controller".constantize
    rescue NameError => e
      raise Mack::Errors::ResourceNotFound.new(self.request.path_info)
    end
  
    c = cont.new
    c.configure_controller(self.request, self.response, self.cookies)
    c.caught_exception = e unless e.nil?

    self.response.controller = c
    return self.response.write(c.run)
  end
end

#setup(env) ⇒ Object

Setup the request, response, cookies, session, etc… yield up, and then clean things up afterwards.



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/mack/application.rb', line 101

def setup(env)
  @request = Mack::Request.new(env) 
  @response = Mack::Response.new
  @cookies = Mack::CookieJar.new(self.request, self.response)
  @runner_helpers = []
  Mack::RunnerHelpers::Registry.registered_items.each do |helper|
    help = helper.new
    help.start(self.request, self.response, self.cookies)
    @runner_helpers << help
  end
end

#teardownObject



113
114
115
116
117
118
# File 'lib/mack/application.rb', line 113

def teardown
  self.runner_helpers.reverse.each do |help|
    help.complete(self.request, self.response, self.cookies)
  end
  # self.response.finish
end

#try_to_find_resource(env, exception) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/mack/application.rb', line 120

def try_to_find_resource(env, exception)
  # we can't find a route for this, so let's try and see if it's in the public directory:
  path = env["PATH_INFO"].dup
  path << ".html" if File.extname(path).blank?
  
  Mack.search_path(:public).each do |p|
    f = File.join(p, path)
    if File.exists?(f)
      return Rack::File.new(p).call(Rack::MockRequest.env_for(path))
    end
  end
  raise exception
end