refactoring
[sinatra.git] / lib / sinatra / event.rb
blob27b8dd35cb85a1a9fd8a17e132eb331b72e7004e
1 module Sinatra
2   
3   module EventManager
4     
5     extend self
7     def events
8       @events || []
9     end
10     
11     def register_event(event)
12       (@events ||= []) << event
13     end
14     
15     def determine_event(verb, path)
16       EventManager.events.detect(method(:not_found)) do |e| 
17         e.path == path && e.verb == verb
18       end
19     end
20     
21     def not_found
22       Event.new(:get, nil) do
23         status 404
24         views_dir SINATRA_ROOT + '/files'
25     
26         if request.path_info == '/'
27           erb :default_index
28         else
29           erb :not_found
30         end
31       end
32     end
33     
34   end
35   
36   class EventContext
38     cattr_accessor :logger
39     
40     attr_reader :request
41     
42     def initialize(request)
43       @request = request
44       @headers = {}
45     end
46     
47     def status(value = nil)
48       @status = value if value
49       @status || 200
50     end
51     
52     def body(value = nil)
53       @body = value if value
54       @body || ''
55     end
56     
57     def error(value = nil)
58       if value
59         @error = value
60         status 500
61       end
62       @error
63     end
64         
65     # This allows for:
66     #  header 'Content-Type' => 'text/html'
67     #  header 'Foo' => 'Bar'
68     # or
69     #  headers 'Content-Type' => 'text/html',
70     #          'Foo' => 'Bar'
71     # 
72     # Whatever blows your hair back
73     def headers(value = nil)
74       @headers.merge!(value) if value
75       @headers
76     end
77     alias :header :headers
78     
79     def params
80       @params ||= @request.params.symbolize_keys
81     end
82     
83     def log_event
84       logger.info "#{request.request_method} #{request.path_info} | Status: #{status} | Params: #{params.inspect}"
85       logger.exception(error) if error
86     end
87     
88   end
89   
90   class Event
92     cattr_accessor :logger
93     cattr_accessor :after_filters
94     
95     self.after_filters = []
96     
97     def self.after_attend(filter)
98       after_filters << filter
99     end
100     
101     after_attend :log_event
102     
103     attr_reader :path, :verb
104     
105     def initialize(verb, path, &block)
106       @verb = verb
107       @path = path
108       @block = block
109       EventManager.register_event(self)
110     end
111     
112     def attend(request)
113       begin
114         context = EventContext.new(request)
115         context.instance_eval(&@block) if @block
116         context
117       rescue => e
118         context.error e
119       end
120       run_through_after_filters(context)
121       context
122     end
123     alias :call :attend
125     private
126     
127       def run_through_after_filters(context)
128         after_filters.each { |filter| context.send(filter) }
129       end
130   end
131