pakyow-core 0.7.2 → 0.8rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -5,7 +5,7 @@ module Pakyow
|
|
5
5
|
attr_accessor :dev_mode, :log, :public_dir, :root, :log_dir,
|
6
6
|
:presenter, :default_action, :ignore_routes, :error_level,
|
7
7
|
:default_environment, :application_path, :log_name, :src_dir,
|
8
|
-
:auto_reload, :errors_in_browser, :static
|
8
|
+
:auto_reload, :errors_in_browser, :static, :all_views_visible
|
9
9
|
|
10
10
|
# Displays development-specific warnings.
|
11
11
|
#
|
@@ -46,7 +46,7 @@ module Pakyow
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def src_dir
|
49
|
-
@src_dir || "#{root}/
|
49
|
+
@src_dir || "#{root}/lib"
|
50
50
|
end
|
51
51
|
|
52
52
|
# Default action
|
@@ -58,6 +58,10 @@ module Pakyow
|
|
58
58
|
def ignore_routes
|
59
59
|
@ignore_routes.nil? ? false : @ignore_routes
|
60
60
|
end
|
61
|
+
|
62
|
+
def all_views_visible
|
63
|
+
@all_views_visible.nil? ? true : @all_views_visible
|
64
|
+
end
|
61
65
|
|
62
66
|
def default_environment
|
63
67
|
@default_environment || :development
|
@@ -2,7 +2,7 @@ module Pakyow
|
|
2
2
|
module Configuration
|
3
3
|
class Server
|
4
4
|
class << self
|
5
|
-
attr_accessor :port, :host
|
5
|
+
attr_accessor :port, :host, :handler
|
6
6
|
|
7
7
|
# On what port does the application run?
|
8
8
|
def port
|
@@ -13,6 +13,11 @@ module Pakyow
|
|
13
13
|
def host
|
14
14
|
@host || '0.0.0.0'
|
15
15
|
end
|
16
|
+
|
17
|
+
# If set, adds a handler to try (e.g. puma)
|
18
|
+
def handler
|
19
|
+
@handler || nil
|
20
|
+
end
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
@@ -9,6 +9,22 @@ module Pakyow
|
|
9
9
|
def response
|
10
10
|
Pakyow.app.response
|
11
11
|
end
|
12
|
+
|
13
|
+
def router
|
14
|
+
RouteLookup.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def params
|
18
|
+
request.params
|
19
|
+
end
|
20
|
+
|
21
|
+
def session
|
22
|
+
request.session
|
23
|
+
end
|
24
|
+
|
25
|
+
def cookies
|
26
|
+
request.cookies
|
27
|
+
end
|
12
28
|
end
|
13
29
|
|
14
30
|
# Helper methods specific to delegates and controllers.
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module Pakyow
|
2
|
-
|
3
2
|
# Handles the loading and reloading of a Pakyow application. If in development
|
4
3
|
# mode, files are automatically reloaded if modified.
|
5
4
|
class Loader
|
6
5
|
|
7
6
|
# Loads files in the provided path, decending into child directories.
|
8
|
-
def
|
7
|
+
def load_from_path(path)
|
9
8
|
require_recursively(path)
|
10
9
|
end
|
11
10
|
|
data/pakyow-core/lib/core/log.rb
CHANGED
@@ -2,20 +2,24 @@ module Pakyow
|
|
2
2
|
|
3
3
|
# Provides an easy way to log text, warnings, etc.
|
4
4
|
class Log
|
5
|
-
|
5
|
+
# Opens stdout and the log file for writing.
|
6
|
+
def self.reopen
|
7
|
+
@@console = $stdout
|
8
|
+
|
9
|
+
d = Configuration::Base.app.log_dir
|
10
|
+
@@file = File.exists?(d) ? File.open("#{d}/#{Configuration::Base.app.log_name}", 'a') : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.close
|
14
|
+
@@file.close if @@file
|
15
|
+
end
|
16
|
+
|
6
17
|
# Adds text to the log.
|
7
18
|
def self.puts(text = "")
|
8
19
|
return if !Configuration::Base.app.log
|
9
20
|
|
10
|
-
@@console ||= $stdout
|
11
21
|
@@console << "#{text}\r\n"
|
12
|
-
|
13
|
-
dir = "#{Configuration::Base.app.log_dir}"
|
14
|
-
|
15
|
-
if File.exists?(dir)
|
16
|
-
@@file ||= File.open("#{dir}/#{Configuration::Base.app.log_name}", 'a')
|
17
|
-
@@file.write "#{text}\r\n"
|
18
|
-
end
|
22
|
+
@@file.write "#{text}\r\n" if @@file
|
19
23
|
end
|
20
24
|
|
21
25
|
class << self
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Middleware
|
3
|
+
class Logger
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
result = nil
|
10
|
+
difference = time { |began_at|
|
11
|
+
Log.enter "Processing #{env['PATH_INFO']} (#{env['REMOTE_ADDR']} at #{began_at}) [#{env['REQUEST_METHOD']}]"
|
12
|
+
|
13
|
+
if error = catch(:error) {
|
14
|
+
result = @app.call(env)
|
15
|
+
nil
|
16
|
+
}
|
17
|
+
Log.enter "[500] #{error}\n"
|
18
|
+
Log.enter error.backtrace.join("\n") + "\n\n"
|
19
|
+
|
20
|
+
result = Pakyow.app.response.finish
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
Log.enter "Completed in #{difference}ms | #{Pakyow.app.response.status} | [#{Pakyow.app.request.url}]"
|
25
|
+
Log.enter
|
26
|
+
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def time
|
31
|
+
s = Time.now
|
32
|
+
yield(s)
|
33
|
+
(Time.now.to_f - s.to_f) * 1000.0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Middleware
|
3
|
+
class NotFound
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
@app.call(env)
|
10
|
+
|
11
|
+
# 404 if no route matched and no views were found
|
12
|
+
unless found?
|
13
|
+
Log.enter "[404] Not Found"
|
14
|
+
|
15
|
+
Pakyow.app.response.body = []
|
16
|
+
Pakyow.app.presenter.reset if Pakyow.app.presenter
|
17
|
+
|
18
|
+
Pakyow.app.response.status = 404
|
19
|
+
Pakyow.app.router.handle!(404)
|
20
|
+
|
21
|
+
if Pakyow.app.presenter
|
22
|
+
# consider moving to presenter middleware
|
23
|
+
# Pakyow.app.presenter.prepare_for_request(Pakyow.app.request)
|
24
|
+
Pakyow.app.response.body = [Pakyow.app.presenter.content] if Pakyow.app.presenter.presented?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def found?
|
32
|
+
return true if Pakyow.app.router.routed?
|
33
|
+
return true if Pakyow.app.presenter && Pakyow.app.presenter.presented? && Configuration::App.all_views_visible
|
34
|
+
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Middleware
|
3
|
+
class Presenter
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
r = Pakyow.app.request
|
10
|
+
|
11
|
+
while(r) do
|
12
|
+
Pakyow.app.presenter.prepare_for_request(Pakyow.app.request)
|
13
|
+
|
14
|
+
r = catch(:rerouted) {
|
15
|
+
@app.call(@env)
|
16
|
+
nil
|
17
|
+
}
|
18
|
+
end
|
19
|
+
#TODO the right thing to do?
|
20
|
+
Pakyow.app.response.body = [Pakyow.app.presenter.content] if Pakyow.app.presenter.presented?
|
21
|
+
Pakyow.app.response.finish
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Middleware
|
3
|
+
class Router
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
catch(:halt) {
|
10
|
+
Pakyow.app.router.route!(Pakyow.app.request)
|
11
|
+
@app.call(env)
|
12
|
+
}
|
13
|
+
rescue StandardError => error
|
14
|
+
Pakyow.app.request.error = error
|
15
|
+
|
16
|
+
Pakyow.app.response.status = 500
|
17
|
+
Pakyow.app.router.handle!(500)
|
18
|
+
|
19
|
+
if Configuration::Base.app.errors_in_browser
|
20
|
+
Pakyow.app.response.body = []
|
21
|
+
Pakyow.app.response.body << "<h4>#{CGI.escapeHTML(error.to_s)}</h4>"
|
22
|
+
Pakyow.app.response.body << error.backtrace.join("<br />")
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
# caught by other middleware (e.g. logger)
|
27
|
+
throw :error, error
|
28
|
+
rescue ArgumentError
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Middleware
|
3
|
+
class Setup
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
#TODO don't track r/r on app; pass through middleware instead (or call in a context that has access to current r/r)
|
10
|
+
Pakyow.app.setup_rr(env)
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Middleware
|
3
|
+
class Static
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
if is_static?(env)
|
10
|
+
response = Rack::Response.new
|
11
|
+
|
12
|
+
catch(:halt) do
|
13
|
+
Pakyow.app.send(File.open(File.join(Configuration::Base.app.public_dir, env['PATH_INFO'])))
|
14
|
+
end
|
15
|
+
else
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def is_static?(env)
|
23
|
+
env['PATH_INFO'] =~ /\.(.*)$/ && File.exists?(File.join(Configuration::Base.app.public_dir, env['PATH_INFO']))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -2,7 +2,13 @@ module Pakyow
|
|
2
2
|
|
3
3
|
# The Request object.
|
4
4
|
class Request < Rack::Request
|
5
|
-
attr_accessor :restful, :
|
5
|
+
attr_accessor :restful, :route_path, :controller, :action, :format, :error, :working_path, :working_method
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
super
|
9
|
+
|
10
|
+
self.setup(self.path)
|
11
|
+
end
|
6
12
|
|
7
13
|
# Easy access to path_info.
|
8
14
|
def path
|
@@ -20,6 +26,10 @@ module Pakyow
|
|
20
26
|
# Set response type
|
21
27
|
Pakyow.app.response["Content-Type"] = Rack::Mime.mime_type(".#{@format}")
|
22
28
|
end
|
29
|
+
|
30
|
+
def session
|
31
|
+
self.env['rack.session'] || {}
|
32
|
+
end
|
23
33
|
|
24
34
|
def cookies
|
25
35
|
@cookies ||= HashUtils.strhash(super)
|
@@ -31,25 +41,25 @@ module Pakyow
|
|
31
41
|
end
|
32
42
|
|
33
43
|
# Returns array of url components.
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
44
|
+
def path_parts
|
45
|
+
@url ||= self.path ? self.class.split_url(self.path) : []
|
46
|
+
end
|
47
|
+
|
48
|
+
def referer
|
49
|
+
@referer ||= self.env['HTTP_REFERER']
|
40
50
|
end
|
41
51
|
|
42
52
|
# Returns array of referer components.
|
43
53
|
def referer_parts
|
44
|
-
|
45
|
-
@referer = self.class.split_url(self.env['HTTP_REFERER'])
|
46
|
-
end
|
47
|
-
|
48
|
-
return @referer
|
54
|
+
@referer_parts ||= self.referer ? self.class.split_url(self.referer) : []
|
49
55
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
56
|
+
|
57
|
+
def setup(path, method = nil)
|
58
|
+
self.set_request_format_from_path(path)
|
59
|
+
self.set_working_path_from_path(path, method)
|
60
|
+
end
|
61
|
+
|
62
|
+
#TODO move to util class
|
53
63
|
def self.split_url(url)
|
54
64
|
arr = []
|
55
65
|
url.split('/').each { |r|
|
@@ -58,5 +68,23 @@ module Pakyow
|
|
58
68
|
|
59
69
|
return arr
|
60
70
|
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def set_working_path_from_path(path, method)
|
75
|
+
base_route, ignore_format = StringUtils.split_at_last_dot(path)
|
76
|
+
|
77
|
+
self.working_path = base_route
|
78
|
+
self.working_method = method || self.method
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_request_format_from_path(path)
|
82
|
+
path, format = StringUtils.split_at_last_dot(path)
|
83
|
+
|
84
|
+
#TODO why it no work without this? was working fine in application
|
85
|
+
return unless format
|
86
|
+
|
87
|
+
self.format = ((format && (format[format.length - 1, 1] == '/')) ? format[0, format.length - 1] : format)
|
88
|
+
end
|
61
89
|
end
|
62
90
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pakyow
|
2
|
+
|
3
|
+
# Handles looking up paths for named routes and populating
|
4
|
+
# the path with data.
|
5
|
+
#
|
6
|
+
class RouteLookup
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
def path(name, data = nil)
|
10
|
+
route = self.get_named_route(name)
|
11
|
+
data ? self.populate(route, data) : File.join('/', route[4])
|
12
|
+
end
|
13
|
+
|
14
|
+
def group(name)
|
15
|
+
@group = name
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def get_named_route(name)
|
22
|
+
Pakyow.app.router.route(name, @group) || []
|
23
|
+
end
|
24
|
+
|
25
|
+
def populate(route, data = {})
|
26
|
+
vars = route[1]
|
27
|
+
|
28
|
+
split_path = Request.split_url(route[4])
|
29
|
+
|
30
|
+
vars.each {|v|
|
31
|
+
split_path[v[:position]] = data[v[:var]]
|
32
|
+
}
|
33
|
+
|
34
|
+
File.join('/', split_path.join('/'))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|