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
@@ -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
|