pakyow-core 0.8.rc4 → 0.8.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6603c6f6c576749182546ee51b5f99a237ba2ab2
4
- data.tar.gz: a986e3adf2e4c33a16e8565b48984947bc1e00e5
3
+ metadata.gz: a272d5c2f6d429275df4e3eac0561c8df6c285e3
4
+ data.tar.gz: 8b21f4193337cd9c7298ccbe0e004bd9c814beb0
5
5
  SHA512:
6
- metadata.gz: 13942daed315f9bf380e9ff718d07458c89d630918d781377117e11aec1dfcab916c5692c769e6148ea37ec74e931c402ae303be62db75f2a77005b293b95d5c
7
- data.tar.gz: 81cddf4aadc79a683129e3420cdf95e42f1e863cbfc123dbe93b92685ac830e533f3f76ca0cae149cc02b4300c5c9a5cb08419023763c7192f5b234ed07da3cf
6
+ metadata.gz: dbb4242d0cbbb4dcce94608b6773026e68c4168c450dd4e7587def70a3db921d5e6d53a7b9cd45b3f718451ec70c8b7cf7878ea998eacf95aed655dc084cea56
7
+ data.tar.gz: b965ed0dd836899da344beb011cd777eb09080fa3013c381d7a4e1194108147f90c58f9be3dfcb0dedce8d6c06519a66d78ea85188a10c992280cb1506173f07
data/pakyow-core/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ = 0.8.0 / 2014-03-02
2
+
3
+ * Major rewrite, including changes to app definition and routing
4
+
1
5
  = 0.7.2 / 2012-02-29
2
6
 
3
7
  * Application server shuts down gracefully
@@ -4,6 +4,7 @@ module Pakyow
4
4
  def reset
5
5
  @@routes = {}
6
6
  @@config = {}
7
+ @@middleware = []
7
8
 
8
9
  @@stacks = {:before => {}, :after => {}}
9
10
  %w(init load process route match error).each {|name|
@@ -16,7 +17,7 @@ module Pakyow
16
17
  #
17
18
  def define(&block)
18
19
  # sets the path to the app file so it can be reloaded later
19
- config.app.path = StringUtils.parse_path_from_caller(caller[0])
20
+ config.app.path = Utils::String.parse_path_from_caller(caller[0])
20
21
 
21
22
  self.instance_eval(&block)
22
23
  end
@@ -32,15 +33,10 @@ module Pakyow
32
33
  end
33
34
  end
34
35
 
35
- # Defines middleware to be loaded.
36
+ # Accepts block to be added to middleware stack.
36
37
  #
37
38
  def middleware(&block)
38
- # prevents middleware from being loaded on each
39
- # request when auto_reload is enabled
40
- return if prepared?
41
-
42
- # tell builder about the middleware
43
- builder.instance_eval(&block)
39
+ @@middleware << block
44
40
  end
45
41
 
46
42
  # Creates an environment.
@@ -144,7 +140,11 @@ module Pakyow
144
140
  envs = envs.empty? || envs.first.nil? ? [config.app.default_environment] : envs
145
141
  load_config(envs)
146
142
 
147
- # load middleware
143
+ # load each block from middleware stack
144
+ @@middleware.each {|mw|
145
+ self.instance_exec(builder, &mw)
146
+ }
147
+
148
148
  builder.use(Rack::MethodOverride)
149
149
  builder.use(Middleware::Static) if config.app.static
150
150
  builder.use(Middleware::Logger) if config.app.log
@@ -185,7 +185,7 @@ module Pakyow
185
185
  include Helpers
186
186
  include AppHelpers
187
187
 
188
- attr_accessor :request, :response
188
+ attr_writer :context
189
189
 
190
190
  def initialize
191
191
  Pakyow.app = self
@@ -217,42 +217,43 @@ module Pakyow
217
217
  def process(env)
218
218
  call_stack(:before, :process)
219
219
 
220
- @response = Response.new
221
- @request = Request.new(env)
222
- @request.app = self
223
- @request.setup
220
+ req = Request.new(env)
221
+ res = Response.new
222
+
223
+ # set response format based on request
224
+ res.format = req.format
225
+
226
+ @context = AppContext.new(req, res)
224
227
 
225
228
  set_initial_cookies
226
229
 
227
230
  @found = false
228
231
  catch(:halt) {
229
- unless config.app.ignore_routes
230
- call_stack(:before, :route)
232
+ call_stack(:before, :route)
231
233
 
232
- @found = @router.perform(@request, self) {
233
- call_stack(:after, :match)
234
- }
234
+ @found = @router.perform(context, self) {
235
+ call_stack(:after, :match)
236
+ }
235
237
 
236
- call_stack(:after, :route)
237
- end
238
+ call_stack(:after, :route)
238
239
 
239
240
  unless found?
240
- handle(404, false)
241
+ handle(404, false)
241
242
 
242
243
  if config.app.errors_in_browser
243
- @response["Content-Type"] = 'text/html'
244
+ response["Content-Type"] = 'text/html'
244
245
 
245
246
  view_file = File.join(File.expand_path('../../', __FILE__), 'views', 'errors', '404.html')
246
247
  content = File.open(view_file).read
247
248
 
248
- path = StringUtils.normalize_path(request.path)
249
+ path = Utils::String.normalize_path(request.path)
249
250
  path = '/' if path.empty?
250
251
 
251
252
  content.gsub!('{view_path}', path == '/' ? 'index.html' : "#{path}.html")
252
253
  content.gsub!('{route_path}', path)
253
254
 
254
- @response.body = []
255
- @response.body << content
255
+ response.body = []
256
+ response.body << content
256
257
  end
257
258
  end
258
259
  }
@@ -261,38 +262,38 @@ module Pakyow
261
262
 
262
263
  call_stack(:after, :process)
263
264
 
264
- @response.finish
265
+ response.finish
265
266
  rescue StandardError => error
266
267
  call_stack(:before, :error)
267
268
 
268
- @request.error = error
269
+ request.error = error
269
270
 
270
271
  handle(500, false) unless found?
271
272
 
272
273
  if config.app.errors_in_browser
273
- @response["Content-Type"] = 'text/html'
274
-
274
+ response["Content-Type"] = 'text/html'
275
+
275
276
  view_file = File.join(File.expand_path('../../', __FILE__), 'views', 'errors', '500.html')
276
277
  content = File.open(view_file).read
277
278
 
278
- path = StringUtils.normalize_path(request.path)
279
+ path = Utils::String.normalize_path(request.path)
279
280
  path = '/' if path.empty?
280
281
 
281
282
  nice_source = error.backtrace[0].match(/^(.+?):(\d+)(|:in `(.+)')$/)
282
283
 
283
284
  content.gsub!('{file}', nice_source[1].gsub(File.expand_path(Config::App.root) + '/', ''))
284
285
  content.gsub!('{line}', nice_source[2])
285
-
286
- content.gsub!('{msg}', error.to_s)
287
- content.gsub!('{trace}', error.backtrace.join('<br>'))
288
286
 
289
- @response.body = []
290
- @response.body << content
287
+ content.gsub!('{msg}', CGI.escapeHTML(error.to_s))
288
+ content.gsub!('{trace}', error.backtrace.map { |bt| CGI.escapeHTML(bt) }.join('<br>'))
289
+
290
+ response.body = []
291
+ response.body << content
291
292
  end
292
293
 
293
294
  call_stack(:after, :error)
294
295
 
295
- @response.finish
296
+ response.finish
296
297
  end
297
298
 
298
299
  def found?
@@ -319,17 +320,17 @@ module Pakyow
319
320
  # Interrupts the application and returns response immediately.
320
321
  #
321
322
  def halt
322
- throw :halt, @response
323
+ throw :halt, response
323
324
  end
324
325
 
325
326
  # Routes the request to different logic.
326
327
  #
327
328
  def reroute(path, method = nil)
328
- @request.setup(path, method)
329
+ request.setup(path, method)
329
330
 
330
331
  call_stack(:before, :route)
331
332
  call_stack(:after, :match)
332
- @router.reroute(@request)
333
+ @router.reroute(request)
333
334
  call_stack(:after, :route)
334
335
  end
335
336
 
@@ -344,7 +345,7 @@ module Pakyow
344
345
  data = file_or_data.read
345
346
 
346
347
  # auto set type based on file type
347
- type = Rack::Mime.mime_type("." + StringUtils.split_at_last_dot(file_or_data.path)[1])
348
+ type = Rack::Mime.mime_type("." + Utils::String.split_at_last_dot(file_or_data.path)[1])
348
349
  else
349
350
  data = file_or_data
350
351
  end
@@ -353,7 +354,7 @@ module Pakyow
353
354
  headers["Content-Type"] = type if type
354
355
  headers["Content-disposition"] = "attachment; filename=#{send_as}" if send_as
355
356
 
356
- @response = Response.new(data, @response.status, @response.header.merge(headers))
357
+ self.context = AppContext.new(request, Response.new(data, response.status, response.header.merge(headers)))
357
358
  halt
358
359
  end
359
360
 
@@ -361,11 +362,11 @@ module Pakyow
361
362
  #
362
363
  def redirect(location, status_code = 302)
363
364
  location = router.path(location) if location.is_a?(Symbol)
364
-
365
+
365
366
  headers = response ? response.header : {}
366
367
  headers = headers.merge({'Location' => location})
367
368
 
368
- app.response = Response.new('', status_code, headers)
369
+ self.context = AppContext.new(request, Response.new('', status_code, headers))
369
370
  halt
370
371
  end
371
372
 
@@ -409,18 +410,18 @@ module Pakyow
409
410
  @router = Router.instance.reset
410
411
  self.class.routes.each_pair {|set_name, block|
411
412
  @router.set(set_name, &block)
412
- }
413
+ } unless config.app.ignore_routes
413
414
  end
414
415
 
415
416
  def set_cookies
416
- @request.cookies.each_pair {|k, v|
417
- @response.unset_cookie(k) if v.nil?
417
+ request.cookies.each_pair {|k, v|
418
+ response.unset_cookie(k) if v.nil?
418
419
 
419
420
  # cookie is already set with value, ignore
420
421
  next if @initial_cookies.include?(k.to_s) && @initial_cookies[k.to_s] == v
421
422
 
422
423
  # set cookie with defaults
423
- @response.set_cookie(k, {
424
+ response.set_cookie(k, {
424
425
  :path => config.cookies.path,
425
426
  :expires => config.cookies.expiration,
426
427
  :value => v
@@ -429,7 +430,7 @@ module Pakyow
429
430
 
430
431
  # delete cookies that are no longer present
431
432
  @initial_cookies.each {|k|
432
- @response.delete_cookie(k) unless @request.cookies.key?(k.to_s)
433
+ response.delete_cookie(k) unless request.cookies.key?(k.to_s)
433
434
  }
434
435
  end
435
436
 
@@ -437,7 +438,7 @@ module Pakyow
437
438
  # for comparison at the end of the cycle
438
439
  def set_initial_cookies
439
440
  @initial_cookies = {}
440
- @request.cookies.each {|k,v|
441
+ request.cookies.each {|k,v|
441
442
  @initial_cookies[k] = v
442
443
  }
443
444
  end
@@ -0,0 +1,10 @@
1
+ module Pakyow
2
+ class AppContext
3
+ attr_reader :request, :response
4
+
5
+ def initialize(request = nil, response = nil)
6
+ @request = request
7
+ @response = response
8
+ end
9
+ end
10
+ end
@@ -5,16 +5,19 @@ require 'core/config/cookies'
5
5
  require 'core/config/logger'
6
6
  require 'core/helpers'
7
7
  require 'core/multilog'
8
+ require 'core/app_context'
8
9
  require 'core/request'
9
10
  require 'core/response'
10
11
  require 'core/loader'
11
12
  require 'core/router'
13
+ require 'core/route_merger'
14
+ require 'core/route_module'
12
15
  require 'core/route_set'
13
16
  require 'core/route_eval'
14
17
  require 'core/route_template_defaults'
15
18
  require 'core/route_lookup'
16
19
  require 'core/app'
17
- require 'core/exceptions'
20
+ require 'core/errors'
18
21
 
19
22
  # middlewares
20
23
  require 'core/middleware/logger'
@@ -0,0 +1,13 @@
1
+ module Pakyow
2
+ # Raised when no app context is available
3
+ class NoContextError < StandardError; end
4
+
5
+ # Raised when route is looked up that doesn't exist
6
+ class MissingRoute < StandardError; end
7
+
8
+ # Raised when template part doesn't exist
9
+ class UnknownTemplatePart < StandardError; end
10
+
11
+ class Error < StandardError; end
12
+ end
13
+
@@ -1,7 +1,10 @@
1
1
  module Pakyow
2
-
3
2
  # For methods that should be accessible anywhere
4
3
  module Helpers
4
+ def context
5
+ @context or raise NoContextError
6
+ end
7
+
5
8
  def logger
6
9
  request.logger
7
10
  end
@@ -11,12 +14,12 @@ module Pakyow
11
14
  end
12
15
 
13
16
  def request
14
- @request
17
+ context.request
15
18
  end
16
19
  alias_method :req, :request
17
20
 
18
21
  def response
19
- @response
22
+ context.response
20
23
  end
21
24
  alias_method :res, :response
22
25
 
@@ -7,21 +7,21 @@ module Pakyow
7
7
  def load_from_path(path)
8
8
  require_recursively(path)
9
9
  end
10
-
10
+
11
11
  protected
12
-
12
+
13
13
  def require_recursively(dir)
14
14
  @times ||= {}
15
15
  if File.exists?(dir)
16
- DirUtils.walk_dir(dir) do |path|
16
+ Utils::Dir.walk_dir(dir) do |path|
17
17
  next if FileTest.directory?(path)
18
18
  next if path.split('.')[-1] != 'rb'
19
-
19
+
20
20
  if Config::Base.app.auto_reload
21
21
  if !@times[path] || (@times[path] && File.mtime(path) - @times[path] > 0)
22
22
  load(path)
23
23
  @times[path] = File.mtime(path)
24
- end
24
+ end
25
25
  else
26
26
  require path
27
27
  end
@@ -11,8 +11,9 @@ module Pakyow
11
11
  if static
12
12
  catch(:halt) do
13
13
  app = Pakyow.app.dup
14
- app.response = Response.new
15
- app.request = Request.new(env)
14
+ res = Response.new
15
+ req = Request.new(env)
16
+ app.context = AppContext.new(req, res)
16
17
  app.send(File.open(resource_path))
17
18
  end
18
19
  else
@@ -2,8 +2,8 @@ module Pakyow
2
2
 
3
3
  # The Request object.
4
4
  class Request < Rack::Request
5
- attr_accessor :restful, :route_path, :controller, :action, :format,
6
- :error, :app, :path, :method, :paths, :methods, :formats
5
+ attr_accessor :restful, :route_path, :controller, :action, :format,
6
+ :error, :path, :method, :paths, :methods, :formats
7
7
 
8
8
  def initialize(*args)
9
9
  super
@@ -14,6 +14,8 @@ module Pakyow
14
14
 
15
15
  @path = path_info
16
16
  @method = request_method.downcase.to_sym
17
+
18
+ setup
17
19
  end
18
20
 
19
21
  def path=(path)
@@ -30,9 +32,6 @@ module Pakyow
30
32
  format = format ? format.to_sym : :html
31
33
  @formats << format
32
34
  @format = format
33
-
34
- # Set response type
35
- @app.response["Content-Type"] = Rack::Mime.mime_type(".#{@format}")
36
35
  end
37
36
 
38
37
  def first_path
@@ -52,12 +51,12 @@ module Pakyow
52
51
  end
53
52
 
54
53
  def cookies
55
- @cookies ||= HashUtils.strhash(super)
54
+ @cookies ||= Utils::Hash.strhash(super)
56
55
  end
57
56
 
58
57
  # Returns indifferent params (see {HashUtils.strhash} for more info on indifferent hashes).
59
58
  def params
60
- @params ||= HashUtils.strhash(super)
59
+ @params ||= Utils::Hash.strhash(super)
61
60
  end
62
61
 
63
62
  # Returns array of url components.
@@ -98,14 +97,14 @@ module Pakyow
98
97
  protected
99
98
 
100
99
  def set_working_path_from_path(path, method)
101
- base_route, ignore_format = StringUtils.split_at_last_dot(path)
100
+ base_route, ignore_format = Utils::String.split_at_last_dot(path)
102
101
 
103
102
  self.path = base_route
104
103
  self.method = method || self.method
105
104
  end
106
105
 
107
106
  def set_request_format_from_path(path)
108
- path, format = StringUtils.split_at_last_dot(path)
107
+ path, format = Utils::String.split_at_last_dot(path)
109
108
  self.format = ((format && (format[format.length - 1, 1] == '/')) ? format[0, format.length - 1] : format)
110
109
  end
111
110
  end