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.
Files changed (42) hide show
  1. data/pakyow-core/bin/pakyow +7 -6
  2. data/pakyow-core/lib/commands/USAGE +2 -1
  3. data/pakyow-core/lib/commands/console.rb +1 -1
  4. data/pakyow-core/lib/commands/server.rb +1 -1
  5. data/pakyow-core/lib/core/application.rb +129 -404
  6. data/pakyow-core/lib/core/base.rb +16 -4
  7. data/pakyow-core/lib/core/configuration/app.rb +6 -2
  8. data/pakyow-core/lib/core/configuration/server.rb +6 -1
  9. data/pakyow-core/lib/core/fn_context.rb +5 -0
  10. data/pakyow-core/lib/core/helpers.rb +16 -0
  11. data/pakyow-core/lib/core/loader.rb +1 -2
  12. data/pakyow-core/lib/core/log.rb +13 -9
  13. data/pakyow-core/lib/core/middleware/logger.rb +37 -0
  14. data/pakyow-core/lib/core/middleware/not_found.rb +40 -0
  15. data/pakyow-core/lib/core/middleware/presenter.rb +25 -0
  16. data/pakyow-core/lib/core/middleware/reloader.rb +14 -0
  17. data/pakyow-core/lib/core/middleware/router.rb +33 -0
  18. data/pakyow-core/lib/core/middleware/setup.rb +15 -0
  19. data/pakyow-core/lib/core/middleware/static.rb +27 -0
  20. data/pakyow-core/lib/core/presenter_base.rb +4 -0
  21. data/pakyow-core/lib/core/request.rb +43 -15
  22. data/pakyow-core/lib/core/response.rb +6 -0
  23. data/pakyow-core/lib/core/route_lookup.rb +37 -0
  24. data/pakyow-core/lib/core/route_set.rb +260 -0
  25. data/pakyow-core/lib/core/route_template.rb +77 -0
  26. data/pakyow-core/lib/core/route_template_defaults.rb +29 -0
  27. data/pakyow-core/lib/core/router.rb +156 -0
  28. data/pakyow-core/lib/generators/pakyow/app/app_generator.rb +12 -2
  29. data/pakyow-core/lib/generators/pakyow/app/templates/app.rb +12 -0
  30. data/pakyow-core/lib/generators/pakyow/app/templates/config.ru +1 -1
  31. data/pakyow-core/lib/generators/pakyow/app/templates/rakefile +1 -1
  32. data/pakyow-core/lib/generators/pakyow/app/templates/{app/views → views}/main.html +0 -0
  33. data/pakyow-core/lib/generators/pakyow/app/templates/{app/views → views}/pakyow.html +1 -1
  34. data/pakyow-core/lib/utils/string.rb +11 -10
  35. metadata +61 -71
  36. data/pakyow-core/lib/core/logger.rb +0 -33
  37. data/pakyow-core/lib/core/reloader.rb +0 -12
  38. data/pakyow-core/lib/core/route_store.rb +0 -220
  39. data/pakyow-core/lib/core/static.rb +0 -25
  40. data/pakyow-core/lib/generators/pakyow/app/templates/app/lib/application_controller.rb +0 -6
  41. data/pakyow-core/lib/generators/pakyow/app/templates/config/application.rb +0 -18
  42. 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}/app/lib"
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
@@ -0,0 +1,5 @@
1
+ module Pakyow
2
+ class FnContext
3
+ include Helpers
4
+ end
5
+ 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 load!(path)
7
+ def load_from_path(path)
9
8
  require_recursively(path)
10
9
  end
11
10
 
@@ -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,14 @@
1
+ module Pakyow
2
+ module Middleware
3
+ class Reloader
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ Pakyow.app.reload
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ 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
@@ -3,5 +3,9 @@ module Pakyow
3
3
  def self.inherited(subclass)
4
4
  Configuration::Base.app.presenter = subclass
5
5
  end
6
+
7
+ def self.instance
8
+ @@instance ||= self.new
9
+ end
6
10
  end
7
11
  end
@@ -2,7 +2,13 @@ module Pakyow
2
2
 
3
3
  # The Request object.
4
4
  class Request < Rack::Request
5
- attr_accessor :restful, :route_spec, :controller, :action, :format, :error, :working_path, :working_method
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 url_parts
35
- unless @url
36
- @url = self.class.split_url(self.env['PATH_INFO'])
37
- end
38
-
39
- return @url
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
- unless @referer
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
- private
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,6 @@
1
+ module Pakyow
2
+
3
+ # The Response object.
4
+ class Response < Rack::Response
5
+ end
6
+ 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