pakyow-core 0.7.2 → 0.8rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/pakyow-core/bin/pakyow +7 -6
- data/pakyow-core/lib/commands/USAGE +2 -1
- data/pakyow-core/lib/commands/console.rb +1 -1
- data/pakyow-core/lib/commands/server.rb +1 -1
- data/pakyow-core/lib/core/application.rb +129 -404
- data/pakyow-core/lib/core/base.rb +16 -4
- data/pakyow-core/lib/core/configuration/app.rb +6 -2
- data/pakyow-core/lib/core/configuration/server.rb +6 -1
- data/pakyow-core/lib/core/fn_context.rb +5 -0
- data/pakyow-core/lib/core/helpers.rb +16 -0
- data/pakyow-core/lib/core/loader.rb +1 -2
- data/pakyow-core/lib/core/log.rb +13 -9
- data/pakyow-core/lib/core/middleware/logger.rb +37 -0
- data/pakyow-core/lib/core/middleware/not_found.rb +40 -0
- data/pakyow-core/lib/core/middleware/presenter.rb +25 -0
- data/pakyow-core/lib/core/middleware/reloader.rb +14 -0
- data/pakyow-core/lib/core/middleware/router.rb +33 -0
- data/pakyow-core/lib/core/middleware/setup.rb +15 -0
- data/pakyow-core/lib/core/middleware/static.rb +27 -0
- data/pakyow-core/lib/core/presenter_base.rb +4 -0
- data/pakyow-core/lib/core/request.rb +43 -15
- data/pakyow-core/lib/core/response.rb +6 -0
- data/pakyow-core/lib/core/route_lookup.rb +37 -0
- data/pakyow-core/lib/core/route_set.rb +260 -0
- data/pakyow-core/lib/core/route_template.rb +77 -0
- data/pakyow-core/lib/core/route_template_defaults.rb +29 -0
- data/pakyow-core/lib/core/router.rb +156 -0
- data/pakyow-core/lib/generators/pakyow/app/app_generator.rb +12 -2
- data/pakyow-core/lib/generators/pakyow/app/templates/app.rb +12 -0
- data/pakyow-core/lib/generators/pakyow/app/templates/config.ru +1 -1
- data/pakyow-core/lib/generators/pakyow/app/templates/rakefile +1 -1
- data/pakyow-core/lib/generators/pakyow/app/templates/{app/views → views}/main.html +0 -0
- data/pakyow-core/lib/generators/pakyow/app/templates/{app/views → views}/pakyow.html +1 -1
- data/pakyow-core/lib/utils/string.rb +11 -10
- metadata +61 -71
- data/pakyow-core/lib/core/logger.rb +0 -33
- data/pakyow-core/lib/core/reloader.rb +0 -12
- data/pakyow-core/lib/core/route_store.rb +0 -220
- data/pakyow-core/lib/core/static.rb +0 -25
- data/pakyow-core/lib/generators/pakyow/app/templates/app/lib/application_controller.rb +0 -6
- data/pakyow-core/lib/generators/pakyow/app/templates/config/application.rb +0 -18
- data/pakyow-core/lib/generators/pakyow/app/templates/logs/requests.log +0 -0
@@ -1,16 +1,12 @@
|
|
1
1
|
module Pakyow
|
2
2
|
class Application
|
3
3
|
class << self
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :core_proc, :middleware_proc, :middlewares, :configurations
|
5
5
|
|
6
6
|
# Sets the path to the application file so it can be reloaded later.
|
7
7
|
#
|
8
8
|
def inherited(subclass)
|
9
|
-
Pakyow::Configuration::App.application_path = parse_path_from_caller(caller[0])
|
10
|
-
end
|
11
|
-
|
12
|
-
def parse_path_from_caller(caller)
|
13
|
-
caller.match(/^(.+)(:?:\d+(:?:in `.+')?$)/)[1]
|
9
|
+
Pakyow::Configuration::App.application_path = StringUtils.parse_path_from_caller(caller[0])
|
14
10
|
end
|
15
11
|
|
16
12
|
# Runs the application. Accepts the environment(s) to run, for example:
|
@@ -19,10 +15,11 @@ module Pakyow
|
|
19
15
|
#
|
20
16
|
def run(*args)
|
21
17
|
return if running?
|
18
|
+
|
22
19
|
@running = true
|
23
20
|
self.builder.run(self.prepare(args))
|
24
21
|
detect_handler.run(builder, :Host => Pakyow::Configuration::Base.server.host, :Port => Pakyow::Configuration::Base.server.port) do |server|
|
25
|
-
trap(:INT)
|
22
|
+
trap(:INT) { stop(server) }
|
26
23
|
trap(:TERM) { stop(server) }
|
27
24
|
end
|
28
25
|
end
|
@@ -70,32 +67,50 @@ module Pakyow
|
|
70
67
|
self.configurations[environment] = block
|
71
68
|
end
|
72
69
|
|
73
|
-
#
|
74
|
-
# routes { get '/' { # do something } }
|
70
|
+
# The block that stores routes, handlers, and hooks.
|
75
71
|
#
|
76
|
-
def
|
77
|
-
self.
|
72
|
+
def core(&block)
|
73
|
+
self.core_proc = block
|
78
74
|
end
|
79
75
|
|
80
|
-
#
|
81
|
-
# The handler can be created one of two ways:
|
82
|
-
#
|
83
|
-
# Define a controller/action handler with an associate response status:
|
84
|
-
# handler(name, 404, :ApplicationController, :handle_404)
|
85
|
-
#
|
86
|
-
# Specify a block as a handler:
|
87
|
-
# handler(name, 404) { # handle error }
|
76
|
+
# The block that stores presenter related things.
|
88
77
|
#
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
def handlers(&block)
|
93
|
-
self.handlers_proc = block
|
78
|
+
def presenter(&block)
|
79
|
+
Configuration::Base.app.presenter.proc = block
|
94
80
|
end
|
95
81
|
|
96
82
|
def middleware(&block)
|
97
83
|
self.middleware_proc = block
|
98
84
|
end
|
85
|
+
|
86
|
+
def before(step, middlewares)
|
87
|
+
middlewares = [middlewares] unless middlewares.is_a?(Array)
|
88
|
+
step = step.to_sym
|
89
|
+
|
90
|
+
self.middlewares ||= {}
|
91
|
+
self.middlewares[step] ||= {}
|
92
|
+
(self.middlewares[step][:before] ||= []).concat(middlewares)
|
93
|
+
end
|
94
|
+
|
95
|
+
def after(step, middlewares)
|
96
|
+
middlewares = [middlewares] unless middlewares.is_a?(Array)
|
97
|
+
step = step.to_sym
|
98
|
+
|
99
|
+
self.middlewares ||= {}
|
100
|
+
self.middlewares[step] ||= {}
|
101
|
+
(self.middlewares[step][:after] ||= []).concat(middlewares)
|
102
|
+
end
|
103
|
+
|
104
|
+
def use(step, type, builder)
|
105
|
+
return unless self.middlewares
|
106
|
+
return unless self.middlewares[step]
|
107
|
+
return unless self.middlewares[step][type]
|
108
|
+
|
109
|
+
self.middlewares[step][type].each { |m|
|
110
|
+
builder.use(m)
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
99
114
|
|
100
115
|
protected
|
101
116
|
|
@@ -106,10 +121,29 @@ module Pakyow
|
|
106
121
|
return if prepared?
|
107
122
|
|
108
123
|
self.builder.use(Rack::MethodOverride)
|
124
|
+
|
125
|
+
self.builder.use(Pakyow::Middleware::Setup)
|
126
|
+
|
127
|
+
#TODO possibly deprecate
|
109
128
|
self.builder.instance_eval(&self.middleware_proc) if self.middleware_proc
|
110
|
-
|
111
|
-
self.builder.use(Pakyow::
|
112
|
-
self.builder.use(Pakyow::
|
129
|
+
|
130
|
+
self.builder.use(Pakyow::Middleware::Static) if Configuration::Base.app.static
|
131
|
+
self.builder.use(Pakyow::Middleware::Logger) if Configuration::Base.app.log
|
132
|
+
self.builder.use(Pakyow::Middleware::Reloader) if Configuration::Base.app.auto_reload
|
133
|
+
|
134
|
+
if Configuration::Base.app.presenter
|
135
|
+
self.use(:presentation, :before, self.builder)
|
136
|
+
self.builder.use(Pakyow::Middleware::Presenter)
|
137
|
+
self.use(:presentation, :after, self.builder)
|
138
|
+
end
|
139
|
+
|
140
|
+
unless Configuration::Base.app.ignore_routes
|
141
|
+
self.use(:routing, :before, self.builder)
|
142
|
+
self.builder.use(Pakyow::Middleware::Router)
|
143
|
+
self.use(:routing, :after, self.builder)
|
144
|
+
end
|
145
|
+
|
146
|
+
self.builder.use(Pakyow::Middleware::NotFound) # always
|
113
147
|
|
114
148
|
@prepared = true
|
115
149
|
|
@@ -128,9 +162,12 @@ module Pakyow
|
|
128
162
|
end
|
129
163
|
|
130
164
|
def detect_handler
|
131
|
-
['thin', 'mongrel', 'webrick']
|
165
|
+
handlers = ['thin', 'mongrel', 'webrick']
|
166
|
+
handlers.unshift(Configuration::Base.server.handler) if Configuration::Base.server.handler
|
167
|
+
|
168
|
+
handlers.each do |handler|
|
132
169
|
begin
|
133
|
-
return Rack::Handler.get(
|
170
|
+
return Rack::Handler.get(handler)
|
134
171
|
rescue LoadError
|
135
172
|
rescue NameError
|
136
173
|
end
|
@@ -151,408 +188,102 @@ module Pakyow
|
|
151
188
|
|
152
189
|
include Helpers
|
153
190
|
|
154
|
-
attr_accessor :request, :response, :presenter, :
|
191
|
+
attr_accessor :request, :response, :presenter, :router
|
155
192
|
|
156
193
|
def initialize
|
157
194
|
Pakyow.app = self
|
158
|
-
@handler_name_to_code = {}
|
159
|
-
@handler_code_to_name = {}
|
160
|
-
|
161
|
-
# This configuration option will be set if a presenter is to be used
|
162
|
-
if Configuration::Base.app.presenter
|
163
|
-
# Create a new instance of the presenter
|
164
|
-
self.presenter = Configuration::Base.app.presenter.new
|
165
|
-
end
|
166
195
|
|
196
|
+
Pakyow.app.presenter = Configuration::Base.app.presenter.instance if Configuration::Base.app.presenter
|
197
|
+
|
167
198
|
# Load application files
|
168
199
|
load_app(false)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Interrupts the application and returns response immediately.
|
172
|
-
#
|
173
|
-
def halt!
|
174
|
-
throw :halt, self.response
|
175
|
-
end
|
176
200
|
|
177
|
-
|
178
|
-
|
179
|
-
self.request.working_path = base_route
|
180
|
-
self.request.working_method = method if method
|
181
|
-
block = prepare_route_block(route, self.request.working_method)
|
182
|
-
throw :new_block, block
|
201
|
+
# Prepare for logging
|
202
|
+
Log.reopen
|
183
203
|
end
|
184
204
|
|
185
|
-
def
|
186
|
-
|
187
|
-
|
188
|
-
code = @handler_name_to_code[name_or_code]
|
189
|
-
self.response.status = code if code
|
190
|
-
throw :new_block, block
|
191
|
-
elsif name = @handler_code_to_name[name_or_code]
|
192
|
-
# we are given a code
|
193
|
-
block = @handler_store[name]
|
194
|
-
self.response.status = name_or_code
|
195
|
-
throw :new_block, block
|
196
|
-
else
|
197
|
-
# no block to be found
|
198
|
-
# do we assume code if a number and set status?
|
199
|
-
self.response.status = name_or_code if name_or_code.is_a?(Fixnum)
|
200
|
-
# still need to stop execution, I think? But do nothing.
|
201
|
-
throw :new_block, nil
|
202
|
-
end
|
205
|
+
def setup_rr(env)
|
206
|
+
self.request = Request.new(env)
|
207
|
+
self.response = Response.new
|
203
208
|
end
|
204
209
|
|
205
210
|
# Called on every request.
|
206
211
|
#
|
207
212
|
def call(env)
|
208
|
-
|
209
|
-
self.response = Rack::Response.new
|
210
|
-
base_route, ignore_format = StringUtils.split_at_last_dot(self.request.path)
|
211
|
-
self.request.working_path = base_route
|
212
|
-
self.request.working_method = self.request.method
|
213
|
-
|
214
|
-
has_route = false
|
215
|
-
catch(:halt) {
|
216
|
-
route_block = prepare_route_block(self.request.path, self.request.method)
|
217
|
-
has_route = true if route_block
|
218
|
-
|
219
|
-
if self.presenter
|
220
|
-
self.presenter.prepare_for_request(self.request)
|
221
|
-
end
|
222
|
-
|
223
|
-
has_route = trampoline(route_block)
|
224
|
-
|
225
|
-
if self.presenter
|
226
|
-
self.response.body = [self.presenter.content]
|
227
|
-
end
|
228
|
-
|
229
|
-
# 404 if no route matched and no views were found
|
230
|
-
if !has_route && (!self.presenter || !self.presenter.presented?)
|
231
|
-
Log.enter "[404] Not Found"
|
232
|
-
handler404 = @handler_store[@handler_code_to_name[404]] if @handler_code_to_name[404]
|
233
|
-
if handler404
|
234
|
-
catch(:halt) {
|
235
|
-
if self.presenter
|
236
|
-
self.presenter.prepare_for_request(self.request)
|
237
|
-
end
|
238
|
-
trampoline(handler404)
|
239
|
-
if self.presenter then
|
240
|
-
self.response.body = [self.presenter.content]
|
241
|
-
end
|
242
|
-
}
|
243
|
-
end
|
244
|
-
self.response.status = 404
|
245
|
-
end
|
246
|
-
} #end :halt catch block
|
247
|
-
|
248
|
-
# This needs to be in the 'return' position (last statement)
|
249
|
-
finish!
|
250
|
-
|
251
|
-
rescue StandardError => error
|
252
|
-
self.request.error = error
|
253
|
-
handler500 = @handler_store[@handler_code_to_name[500]] if @handler_code_to_name[500]
|
254
|
-
if handler500
|
255
|
-
catch(:halt) {
|
256
|
-
if self.presenter
|
257
|
-
self.presenter.prepare_for_request(self.request)
|
258
|
-
end
|
259
|
-
trampoline(handler500)
|
260
|
-
if self.presenter then
|
261
|
-
self.response.body = [self.presenter.content]
|
262
|
-
end
|
263
|
-
} #end :halt catch block
|
264
|
-
end
|
265
|
-
self.response.status = 500
|
266
|
-
|
267
|
-
if Configuration::Base.app.errors_in_browser
|
268
|
-
self.response.body = []
|
269
|
-
self.response.body << "<h4>#{CGI.escapeHTML(error.to_s)}</h4>"
|
270
|
-
self.response.body << error.backtrace.join("<br />")
|
271
|
-
end
|
272
|
-
|
273
|
-
begin
|
274
|
-
# caught by other middleware (e.g. logger)
|
275
|
-
throw :error, error
|
276
|
-
rescue ArgumentError
|
277
|
-
end
|
278
|
-
|
279
|
-
finish!
|
280
|
-
end
|
281
|
-
|
282
|
-
# Sends a file in the response (immediately). Accepts a File object. Mime
|
283
|
-
# type is automatically detected.
|
284
|
-
#
|
285
|
-
def send_file!(source_file, send_as = nil, type = nil)
|
286
|
-
path = source_file.is_a?(File) ? source_file.path : source_file
|
287
|
-
send_as ||= path
|
288
|
-
type ||= Rack::Mime.mime_type(".#{send_as.split('.')[-1]}")
|
289
|
-
|
290
|
-
data = ""
|
291
|
-
File.open(path, "r").each_line { |line| data << line }
|
292
|
-
|
293
|
-
self.response = Rack::Response.new(data, self.response.status, self.response.header.merge({ "Content-Type" => type }))
|
294
|
-
halt!
|
213
|
+
finish
|
295
214
|
end
|
296
215
|
|
297
|
-
#
|
298
|
-
|
299
|
-
|
300
|
-
def send_data!(data, type, file_name = nil)
|
301
|
-
status = self.response ? self.response.status : 200
|
302
|
-
|
303
|
-
headers = self.response ? self.response.header : {}
|
304
|
-
headers = headers.merge({ "Content-Type" => type })
|
305
|
-
headers = headers.merge({ "Content-disposition" => "attachment; filename=#{file_name}"}) if file_name
|
306
|
-
|
307
|
-
self.response = Rack::Response.new(data, status, headers)
|
308
|
-
halt!
|
216
|
+
# This is NOT a useless method, it's a part of the external api
|
217
|
+
def reload
|
218
|
+
load_app
|
309
219
|
end
|
310
220
|
|
311
|
-
# Redirects to location (immediately).
|
312
|
-
#
|
313
|
-
def redirect_to!(location, status_code = 302)
|
314
|
-
headers = self.response ? self.response.header : {}
|
315
|
-
headers = headers.merge({'Location' => location})
|
316
|
-
|
317
|
-
self.response = Rack::Response.new('', status_code, headers)
|
318
|
-
halt!
|
319
|
-
end
|
320
221
|
|
321
|
-
#
|
322
|
-
# get('/', :ControllerClass, :action_method)
|
323
|
-
# get('/') { # do something }
|
324
|
-
#
|
325
|
-
# Routes for namespaced controllers (e.g. Admin::ControllerClass) can be defined like this:
|
326
|
-
# get('/', :Admin_ControllerClass, :action_method)
|
327
|
-
#
|
328
|
-
def get(route, *args, &block)
|
329
|
-
register_route(:user, route, block, :get, *args)
|
330
|
-
end
|
222
|
+
# APP ACTIONS
|
331
223
|
|
332
|
-
#
|
224
|
+
# Interrupts the application and returns response immediately.
|
333
225
|
#
|
334
|
-
def
|
335
|
-
|
226
|
+
def halt
|
227
|
+
throw :halt, response
|
336
228
|
end
|
337
229
|
|
338
|
-
#
|
230
|
+
# Routes the request to different logic.
|
339
231
|
#
|
340
|
-
def
|
341
|
-
|
342
|
-
end
|
232
|
+
def reroute(path, method = nil)
|
233
|
+
self.request.setup(path, method)
|
343
234
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
235
|
+
begin
|
236
|
+
# caught by other middleware (e.g. presenter) that does something with the
|
237
|
+
# new request then hands it back down to the router
|
238
|
+
throw :rerouted, request
|
239
|
+
rescue ArgumentError
|
240
|
+
# nobody caught it, so tell the router to reroute
|
241
|
+
app.router.reroute!(request)
|
242
|
+
end
|
348
243
|
end
|
349
244
|
|
350
|
-
#
|
245
|
+
# Sends data in the response (immediately). Accepts a string of data or a File,
|
246
|
+
# mime-type (auto-detected; defaults to octet-stream), and optional file name.
|
351
247
|
#
|
352
|
-
|
353
|
-
|
354
|
-
end
|
355
|
-
|
356
|
-
# Creates REST routes for a resource. Arguments: url, controller, model, hooks
|
248
|
+
# If a File, mime type will be guessed. Otherwise mime type and file name will
|
249
|
+
# default to whatever is set in the response.
|
357
250
|
#
|
358
|
-
def
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
nest_scope(&block) if block_given?
|
363
|
-
|
364
|
-
@restful_routes ||= {}
|
365
|
-
@restful_routes[model] ||= {} if model
|
366
|
-
|
367
|
-
@@restful_actions.each do |opts|
|
368
|
-
action_url = current_path
|
369
|
-
if suffix = opts[:url_suffix]
|
370
|
-
action_url = File.join(action_url, suffix)
|
371
|
-
end
|
372
|
-
|
373
|
-
# Create the route
|
374
|
-
register_route(:restful, action_url, nil, opts[:method], controller, opts[:action], hooks)
|
375
|
-
|
376
|
-
# Store url for later use (currently used by Binder#action)
|
377
|
-
@restful_routes[model][opts[:action]] = action_url if model
|
378
|
-
end
|
379
|
-
|
380
|
-
remove_scope
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
@@restful_actions = [
|
385
|
-
{ :action => :edit, :method => :get, :url_suffix => 'edit/:id' },
|
386
|
-
{ :action => :show, :method => :get, :url_suffix => ':id' },
|
387
|
-
{ :action => :new, :method => :get, :url_suffix => 'new' },
|
388
|
-
{ :action => :update, :method => :put, :url_suffix => ':id' },
|
389
|
-
{ :action => :delete, :method => :delete, :url_suffix => ':id' },
|
390
|
-
{ :action => :index, :method => :get },
|
391
|
-
{ :action => :create, :method => :post }
|
392
|
-
]
|
393
|
-
|
394
|
-
def hook(name, controller = nil, action = nil, &block)
|
395
|
-
block = build_controller_block(controller, action) if controller
|
396
|
-
@route_store.add_hook(name, block)
|
397
|
-
end
|
398
|
-
|
399
|
-
def handler(name, *args, &block)
|
400
|
-
code, controller, action = parse_handler_args(args)
|
251
|
+
def send(file_or_data, type = nil, send_as = nil)
|
252
|
+
case file_or_data.class
|
253
|
+
when File
|
254
|
+
data = File.open(path, "r").each_line { |line| data << line }
|
401
255
|
|
402
|
-
|
403
|
-
|
256
|
+
# auto set type based on file type
|
257
|
+
type = Rack::Mime.mime_type("." + StringUtils.split_at_last_dot(File.path))[1]
|
404
258
|
else
|
405
|
-
|
259
|
+
data = file_or_data
|
406
260
|
end
|
407
261
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
#TODO: don't like this...
|
415
|
-
def reload
|
416
|
-
load_app
|
417
|
-
end
|
418
|
-
|
419
|
-
def session
|
420
|
-
self.request.env['rack.session'] || {}
|
421
|
-
end
|
422
|
-
|
423
|
-
protected
|
424
|
-
|
425
|
-
def prepare_route_block(route, method)
|
426
|
-
set_request_format_from_route(route)
|
427
|
-
base_route, ignore_format = StringUtils.split_at_last_dot(route)
|
428
|
-
|
429
|
-
if Pakyow::Configuration::App.ignore_routes
|
430
|
-
controller_block, packet = nil, {:vars=>{}, :data=>nil}
|
431
|
-
else
|
432
|
-
controller_block, packet = @route_store.get_block(base_route, method)
|
433
|
-
end
|
262
|
+
headers = {}
|
263
|
+
headers["Content-Type"] = type if type
|
264
|
+
headers["Content-disposition"] = "attachment; filename=#{send_as}" if send_as
|
434
265
|
|
435
|
-
|
436
|
-
|
437
|
-
self.request.restful = packet[:data][:restful] if packet[:data]
|
438
|
-
|
439
|
-
controller_block
|
266
|
+
app.response = Rack::Response.new(data, response.status, response.header.merge(headers))
|
267
|
+
halt
|
440
268
|
end
|
441
269
|
|
442
|
-
|
443
|
-
last_call_has_block = (block == nil) ? false : true
|
444
|
-
while block do
|
445
|
-
block = catch(:new_block) {
|
446
|
-
block.call()
|
447
|
-
# Getting here means that call() returned normally (not via a throw)
|
448
|
-
:fall_through
|
449
|
-
} # end :invoke_route catch block
|
450
|
-
# If invoke_route! or invoke_handler! was called in the block, block will have a new value (nil or block).
|
451
|
-
# If neither was called, block will be :fall_through
|
452
|
-
|
453
|
-
if block == nil
|
454
|
-
last_call_has_block = false
|
455
|
-
elsif block == :fall_through
|
456
|
-
last_call_has_block = true
|
457
|
-
block = nil
|
458
|
-
end
|
459
|
-
|
460
|
-
if block && self.presenter
|
461
|
-
self.presenter.prepare_for_request(self.request)
|
462
|
-
end
|
463
|
-
end
|
464
|
-
last_call_has_block
|
465
|
-
end
|
466
|
-
|
467
|
-
def parse_route_args(args)
|
468
|
-
controller = args[0] if args[0] && (args[0].is_a?(Symbol) || args[0].is_a?(String))
|
469
|
-
action = args[1] if controller
|
470
|
-
hooks = args[2] if controller
|
471
|
-
unless controller
|
472
|
-
hooks = args[0] if args[0] && args[0].is_a?(Hash)
|
473
|
-
end
|
474
|
-
return controller, action, hooks
|
475
|
-
end
|
476
|
-
|
477
|
-
def parse_restful_args(args)
|
478
|
-
model = args[0] if args[0] && (args[0].is_a?(Symbol) || args[0].is_a?(String))
|
479
|
-
hooks = args[1] if model
|
480
|
-
unless model
|
481
|
-
hooks = args[0] if args[0] && args[0].is_a?(Hash)
|
482
|
-
end
|
483
|
-
return model, hooks
|
484
|
-
end
|
485
|
-
|
486
|
-
def parse_handler_args(args)
|
487
|
-
code = args[0] if args[0] && args[0].is_a?(Fixnum)
|
488
|
-
controller = args[1] if code && args[1]
|
489
|
-
action = args[2] if controller && args[2]
|
490
|
-
unless code
|
491
|
-
controller = args[0] if args[0]
|
492
|
-
action = args[1] if controller && args[1]
|
493
|
-
end
|
494
|
-
return code, controller, action
|
495
|
-
end
|
496
|
-
|
497
|
-
# Handles route registration.
|
270
|
+
# Redirects to location (immediately).
|
498
271
|
#
|
499
|
-
def
|
500
|
-
|
501
|
-
|
502
|
-
block = build_controller_block(controller, action)
|
503
|
-
end
|
504
|
-
|
505
|
-
data = {:route_type=>type, :route_spec=>route}
|
506
|
-
if type == :restful
|
507
|
-
data[:restful] = {:restful_action=>action}
|
508
|
-
end
|
509
|
-
@route_store.add_route(route, block, method, data, hooks)
|
510
|
-
end
|
511
|
-
|
512
|
-
def build_controller_block(controller, action)
|
513
|
-
controller = eval(controller.to_s)
|
514
|
-
action ||= Configuration::Base.app.default_action
|
515
|
-
|
516
|
-
block = lambda {
|
517
|
-
instance = controller.new
|
518
|
-
request.controller = instance
|
519
|
-
request.action = action
|
520
|
-
|
521
|
-
instance.send(action)
|
522
|
-
}
|
523
|
-
|
524
|
-
block
|
525
|
-
end
|
526
|
-
|
527
|
-
def set_request_format_from_route(route)
|
528
|
-
route, format = StringUtils.split_at_last_dot(route)
|
529
|
-
self.request.format = ((format && (format[format.length - 1, 1] == '/')) ? format[0, format.length - 1] : format)
|
530
|
-
end
|
531
|
-
|
532
|
-
def with_scope(opts)
|
533
|
-
@scope ||= {}
|
534
|
-
@scope[:path] ||= []
|
535
|
-
@scope[:model] = opts[:model]
|
536
|
-
|
537
|
-
@scope[:path] << opts[:url]
|
538
|
-
|
539
|
-
yield
|
540
|
-
end
|
272
|
+
def redirect(location, status_code = 302)
|
273
|
+
headers = response ? response.header : {}
|
274
|
+
headers = headers.merge({'Location' => location})
|
541
275
|
|
542
|
-
|
543
|
-
|
276
|
+
app.response = Rack::Response.new('', status_code, headers)
|
277
|
+
halt
|
544
278
|
end
|
545
279
|
|
546
|
-
def
|
547
|
-
|
548
|
-
yield
|
549
|
-
@scope[:path].pop
|
280
|
+
def handle(name_or_code)
|
281
|
+
app.router.handle!(name_or_code, true)
|
550
282
|
end
|
551
283
|
|
552
|
-
|
553
|
-
@scope[:path].join('/')
|
554
|
-
end
|
284
|
+
protected
|
555
285
|
|
286
|
+
#TODO need configuration options for cookies (plus ability to override for each?)
|
556
287
|
def set_cookies
|
557
288
|
if self.request.cookies && self.request.cookies != {}
|
558
289
|
self.request.cookies.each do |key, value|
|
@@ -573,30 +304,24 @@ module Pakyow
|
|
573
304
|
load(Configuration::App.application_path) if reload_app
|
574
305
|
|
575
306
|
@loader = Loader.new unless @loader
|
576
|
-
@loader.
|
307
|
+
@loader.load_from_path(Configuration::Base.app.src_dir)
|
577
308
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
# Reload views
|
582
|
-
if self.presenter
|
583
|
-
self.presenter.load
|
584
|
-
end
|
309
|
+
self.load_core
|
310
|
+
self.presenter.load if self.presenter
|
585
311
|
end
|
586
312
|
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
313
|
+
# Evaluates core_proc
|
314
|
+
#
|
315
|
+
def load_core
|
316
|
+
@router = Router.instance.reset
|
591
317
|
|
592
|
-
|
593
|
-
@route_store = RouteStore.new
|
594
|
-
self.instance_eval(&self.class.routes_proc) if self.class.routes_proc
|
318
|
+
@router.set(:default, &self.class.core_proc) if self.class.core_proc
|
595
319
|
end
|
596
320
|
|
597
321
|
# Send the response and cleanup.
|
598
322
|
#
|
599
|
-
|
323
|
+
#TODO remove exclamation
|
324
|
+
def finish
|
600
325
|
set_cookies
|
601
326
|
self.response.finish
|
602
327
|
end
|
@@ -2,14 +2,26 @@ require 'core/configuration/base'
|
|
2
2
|
require 'core/helpers'
|
3
3
|
require 'core/log'
|
4
4
|
require 'core/request'
|
5
|
+
require 'core/response'
|
5
6
|
require 'core/loader'
|
7
|
+
require 'core/router'
|
8
|
+
require 'core/route_set'
|
9
|
+
require 'core/route_template'
|
10
|
+
require 'core/route_template_defaults'
|
11
|
+
require 'core/route_lookup'
|
6
12
|
require 'core/application'
|
7
|
-
require 'core/route_store'
|
8
|
-
require 'core/logger'
|
9
|
-
require 'core/static'
|
10
|
-
require 'core/reloader'
|
11
13
|
require 'core/cache'
|
12
14
|
require 'core/presenter_base'
|
15
|
+
require 'core/fn_context'
|
16
|
+
|
17
|
+
# middlewares
|
18
|
+
require 'core/middleware/logger'
|
19
|
+
require 'core/middleware/static'
|
20
|
+
require 'core/middleware/reloader'
|
21
|
+
require 'core/middleware/presenter'
|
22
|
+
require 'core/middleware/not_found'
|
23
|
+
require 'core/middleware/router'
|
24
|
+
require 'core/middleware/setup'
|
13
25
|
|
14
26
|
# utils
|
15
27
|
require 'utils/string'
|