racket-mvc 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -5
  3. data/lib/racket.rb +25 -7
  4. data/lib/racket/application.rb +70 -136
  5. data/lib/racket/controller.rb +95 -38
  6. data/lib/racket/current.rb +1 -1
  7. data/lib/racket/helpers/file.rb +7 -5
  8. data/lib/racket/helpers/routing.rb +5 -5
  9. data/lib/racket/helpers/sass.rb +11 -11
  10. data/lib/racket/helpers/view.rb +8 -5
  11. data/lib/racket/plugins/base.rb +1 -1
  12. data/lib/racket/plugins/sass.rb +1 -1
  13. data/lib/racket/request.rb +3 -3
  14. data/lib/racket/response.rb +1 -1
  15. data/lib/racket/router.rb +31 -12
  16. data/lib/racket/session.rb +3 -3
  17. data/lib/racket/settings/application.rb +27 -33
  18. data/lib/racket/settings/base.rb +19 -8
  19. data/lib/racket/settings/controller.rb +9 -7
  20. data/lib/racket/settings/defaults.rb +81 -0
  21. data/lib/racket/utils.rb +19 -15
  22. data/lib/racket/utils/application.rb +4 -114
  23. data/lib/racket/utils/application/handler_stack.rb +163 -0
  24. data/lib/racket/utils/application/logger.rb +72 -0
  25. data/lib/racket/utils/application/registry_builder.rb +88 -0
  26. data/lib/racket/utils/application/stateless_services.rb +73 -0
  27. data/lib/racket/utils/exceptions.rb +3 -3
  28. data/lib/racket/utils/file_system.rb +75 -47
  29. data/lib/racket/utils/helpers.rb +35 -13
  30. data/lib/racket/utils/routing.rb +62 -46
  31. data/lib/racket/utils/views.rb +19 -187
  32. data/lib/racket/utils/views/renderer.rb +75 -0
  33. data/lib/racket/utils/views/template_cache.rb +126 -0
  34. data/lib/racket/utils/views/template_locator.rb +83 -0
  35. data/lib/racket/utils/views/template_resolver.rb +112 -0
  36. data/lib/racket/version.rb +2 -2
  37. data/lib/racket/view_manager.rb +12 -4
  38. data/rake/utils.rb +5 -5
  39. data/spec/_custom.rb +69 -19
  40. data/spec/_default.rb +60 -44
  41. data/spec/_plugin.rb +12 -14
  42. data/spec/_template_cache.rb +176 -0
  43. data/spec/racket.rb +10 -13
  44. data/spec/test_custom_app/controllers/sub1/custom_sub_controller_1.rb +1 -1
  45. data/spec/test_custom_app/controllers/sub3/custom_sub_controller_3.rb +19 -1
  46. data/spec/test_custom_app/controllers/sub5/custom_sub_controller_5.rb +8 -0
  47. data/spec/test_custom_app/files/stuff.rb +3 -0
  48. data/spec/test_custom_app/files/triplet.erb +5 -0
  49. data/spec/test_custom_app/templates/sub5/text.erb +3 -0
  50. data/spec/test_default_app/controllers/default_root_controller.rb +3 -0
  51. data/spec/test_default_app/controllers/sub1/default_sub_controller_1.rb +1 -1
  52. metadata +52 -11
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -23,8 +23,9 @@ module Racket
23
23
  module File
24
24
  # Class for sending files.
25
25
  class Response
26
- def initialize(file, options)
27
- @file = Utils.build_path(file)
26
+ def initialize(utils, file, options)
27
+ @utils = utils
28
+ @file = @utils.build_path(file)
28
29
  @options = options
29
30
  @response = Racket::Response.new
30
31
  build
@@ -40,7 +41,7 @@ module Racket
40
41
  private
41
42
 
42
43
  def build
43
- if Utils.file_readable?(@file) then build_success
44
+ if Racket::Utils::FileSystem.file_readable?(@file) then build_success
44
45
  else build_failure
45
46
  end
46
47
  end
@@ -82,7 +83,8 @@ module Racket
82
83
  # @param [Hash] options
83
84
  # @return [Array]
84
85
  def send_file(file, options = {})
85
- respond!(*(Response.new(file, options).to_a))
86
+ response = Response.new(Controller.context.utils, file, options).to_a
87
+ respond!(*response)
86
88
  end
87
89
  end
88
90
  end
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -28,10 +28,10 @@ module Racket
28
28
  # @param [Array] params
29
29
  # @return [String]
30
30
  def route(controller, action = nil, *params)
31
- Application.get_route(controller, action, params)
31
+ controller.get_route(action, params)
32
32
  end
33
33
 
34
- alias_method(:r, :route)
34
+ alias r route
35
35
 
36
36
  # Returns a route to an action within the current controller.
37
37
  #
@@ -39,10 +39,10 @@ module Racket
39
39
  # @param [Array] params
40
40
  # @return [String]
41
41
  def route_self(action = nil, *params)
42
- Application.get_route(self.class, action, params)
42
+ self.class.get_route(action, params)
43
43
  end
44
44
 
45
- alias_method(:rs, :route_self)
45
+ alias rs route_self
46
46
  end
47
47
  end
48
48
  end
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -26,24 +26,24 @@ module Racket
26
26
  # @param [Symbol] sym
27
27
  # @return [String]
28
28
  def css(sym)
29
- route = Application.get_route(self.class)
29
+ route = self.class.get_route
30
30
  route = '' if route == '/' # Special case for root controller
31
31
  "/css#{route}/#{sym}.css"
32
32
  end
33
33
 
34
- def self.add_template_location(route)
35
- root_dir = Application.settings.root_dir
36
- sass_dir = Utils.build_path(root_dir, 'sass', route).to_s
37
- css_dir = Utils.build_path(root_dir, 'public', 'css', route).to_s
34
+ def self.add_template_location(klass, route)
35
+ utils = klass.context.utils
36
+ sass_dir = utils.build_path('sass', route).to_s
37
+ css_dir = utils.build_path('public', 'css', route).to_s
38
38
  ::Sass::Plugin.add_template_location(sass_dir, css_dir)
39
39
  sass_dir
40
40
  end
41
41
 
42
- def self.add_warmup_urls(sass_dir, route)
42
+ def self.add_warmup_urls(klass, sass_dir, route)
43
43
  Dir.chdir(sass_dir) do
44
44
  basedir = route.empty? ? '/css' : "/css/#{route}"
45
45
  Dir.glob('*.s[ac]ss').each do |file|
46
- Application.settings.warmup_urls << "#{basedir}/#{::File.basename(file, '.*')}.css"
46
+ klass.settings.fetch(:warmup_urls) << "#{basedir}/#{::File.basename(file, '.*')}.css"
47
47
  end
48
48
  end
49
49
  end
@@ -54,9 +54,9 @@ module Racket
54
54
  # @param [Class] klass
55
55
  # @return [nil]
56
56
  def self.included(klass)
57
- route = Application.get_route(klass)[1..-1] # Remove leading slash
58
- sass_dir = add_template_location(route)
59
- add_warmup_urls(sass_dir, route)
57
+ route = klass.get_route.slice(1..-1) # Remove leading slash
58
+ sass_dir = add_template_location(klass, route)
59
+ add_warmup_urls(klass, sass_dir, route)
60
60
  nil
61
61
  end
62
62
 
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -26,10 +26,13 @@ module Racket
26
26
  # @param [String] template
27
27
  # @param [Object] context
28
28
  # @return [String|nil]
29
- def render_template(template, context = self)
30
- template = Utils.build_path(template)
31
- return nil unless Utils.file_readable?(template)
32
- Tilt.new(template).render(context)
29
+ # @todo Allow user to specify template options
30
+ def render_template(template, context = self, template_settings = nil)
31
+ utils = Controller.context.utils
32
+ template = utils.build_path(template)
33
+ return nil unless Racket::Utils::FileSystem.file_readable?(template)
34
+ settings = ::Racket::Utils::Views.extract_template_settings(context, template_settings)
35
+ Tilt.new(template, nil, settings).render(context)
33
36
  end
34
37
  end
35
38
  end
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -27,7 +27,7 @@ module Racket
27
27
  undef_method :session, :session_options
28
28
 
29
29
  # Redefine methods for handling GET parameters
30
- alias_method(:get_params, :GET)
30
+ alias get_params GET
31
31
  undef_method :GET
32
32
 
33
33
  # Returns a value from the GET parameter hash.
@@ -40,7 +40,7 @@ module Racket
40
40
  end
41
41
 
42
42
  # Redefine methods for handling POST parameters
43
- alias_method(:post_params, :POST)
43
+ alias post_params POST
44
44
  undef_method :POST
45
45
 
46
46
  # Returns a value from the POST parameter hash.
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -16,6 +16,7 @@
16
16
  # You should have received a copy of the GNU Affero General Public License
17
17
  # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
18
 
19
+ require 'ostruct'
19
20
  require 'set'
20
21
 
21
22
  require 'http_router'
@@ -34,13 +35,31 @@ module Racket
34
35
  end
35
36
  end
36
37
 
37
- attr_reader :action_cache
38
38
  attr_reader :routes
39
39
 
40
- def initialize
40
+ # Returns a service proc that can be used by the registry.
41
+ #
42
+ # @param [Hash] _options (unused)
43
+ # @return [Proc]
44
+ def self.service(_options = {})
45
+ lambda do |reg|
46
+ new(
47
+ action_cache: reg.action_cache,
48
+ dev_mode: reg.application_settings.mode == :dev,
49
+ logger: reg.application_logger
50
+ )
51
+ end
52
+ end
53
+
54
+ # @return [Racket::Utils::Routing::ActionCache]
55
+ def action_cache
56
+ @options.action_cache
57
+ end
58
+
59
+ def initialize(options)
60
+ @options = OpenStruct.new(options)
41
61
  @router = HttpRouter.new
42
62
  @routes = {}
43
- @action_cache = Utils::Routing::ActionCache.new
44
63
  end
45
64
 
46
65
  # Returns a route to the specified controller/action/parameter combination.
@@ -50,7 +69,7 @@ module Racket
50
69
  # @param [Array] params
51
70
  # @return [String]
52
71
  def get_route(controller_class, action, params)
53
- fail "Cannot find controller #{controller_class}" unless @routes.key?(controller_class)
72
+ raise "Cannot find controller #{controller_class}" unless @routes.key?(controller_class)
54
73
  params.flatten!
55
74
  Route.new(@routes[controller_class], action, params).to_s
56
75
  end
@@ -63,13 +82,13 @@ module Racket
63
82
  def map(path, controller_class)
64
83
  map_controller(path.empty? ? '/' : path, controller_class)
65
84
  @router.add("#{path}(/*params)").to(controller_class)
66
- @action_cache.add(controller_class)
85
+ action_cache.add(controller_class)
67
86
  end
68
87
 
69
88
  # @todo: Allow the user to set custom handlers for different errors
70
89
  def render_error(status, error = nil)
71
90
  # If running in dev mode, let Rack::ShowExceptions handle the error.
72
- fail(error) if error && Application.dev_mode?
91
+ raise error if error && @options.dev_mode
73
92
 
74
93
  # Not running in dev mode, let us handle the error ourselves.
75
94
  Response.generate_error_response(status)
@@ -83,7 +102,7 @@ module Racket
83
102
  catch :response do # Catches early exits from Controller.respond.
84
103
  # Ensure that that a controller will respond to the request. If not, send a 404.
85
104
  return render_error(404) unless (target_info = target_info(env))
86
- Utils.render_controller(env, target_info)
105
+ Racket::Utils::Routing::Dispatcher.new(env, target_info).dispatch
87
106
  end
88
107
  rescue => err
89
108
  render_error(500, err)
@@ -92,7 +111,7 @@ module Racket
92
111
  private
93
112
 
94
113
  def map_controller(base_path, controller_class)
95
- Application.inform_dev("Mapping #{controller_class} to #{base_path}.")
114
+ @options.logger.inform_dev("Mapping #{controller_class} to #{base_path}.")
96
115
  @routes[controller_class] = base_path
97
116
  end
98
117
 
@@ -105,10 +124,10 @@ module Racket
105
124
  matching_route = @router.recognize(env).first
106
125
  # Exit early if no controller is responsible for the route
107
126
  return nil unless matching_route
108
- # Some controller is claiming to be responsible for the route
109
- result = Utils.extract_target(matching_route.first)
127
+ # Some controller is claiming to be responsible for the route, find out which one.
128
+ result = Racket::Utils::Routing::Dispatcher.extract_target(matching_route.first)
110
129
  # Exit early if action is not available on target
111
- return nil unless @action_cache.present?(result.first, result.last)
130
+ return nil unless action_cache.present?(result.first, result.last)
112
131
  result
113
132
  end
114
133
  end
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -29,7 +29,7 @@ module Racket
29
29
  def inspect
30
30
  "#<#{self.class}:#{object_id}>"
31
31
  end
32
- alias_method(:to_s, :inspect)
33
- alias_method(:to_str, :inspect)
32
+ alias to_s inspect
33
+ alias to_str inspect
34
34
  end
35
35
  end
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -16,39 +16,31 @@
16
16
  # You should have received a copy of the GNU Affero General Public License
17
17
  # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
18
 
19
- require 'logger'
20
-
21
19
  require_relative 'base.rb'
20
+ require_relative 'defaults.rb'
22
21
 
23
22
  module Racket
24
23
  module Settings
25
24
  # Class for storing application settings.
26
25
  class Application < Base
27
- setting(:default_action, :index)
28
- setting(:default_content_type, 'text/html')
29
- setting(:default_controller_helpers, [:routing, :view])
30
- setting(:default_layout, nil)
31
- setting(:default_view, nil)
32
- setting(:logger, Logger.new($stdout))
33
- setting(:middleware, [])
34
- setting(:mode, :live)
35
- setting(:plugins, [])
36
- setting(
37
- :session_handler,
38
- [
39
- Rack::Session::Cookie,
40
- {
41
- key: 'racket.session',
42
- old_secret: SecureRandom.hex(16),
43
- secret: SecureRandom.hex(16)
44
- }
45
- ]
46
- )
47
- setting(:root_dir, nil) # Will be set automatically by constructor.
48
- setting(:warmup_urls, Set.new)
26
+ @defaults = Defaults.application_defaults
27
+
28
+ [
29
+ :default_action, :default_content_type, :default_controller_helpers,
30
+ :default_layout, :default_view, :logger, :middleware, :mode, :plugins,
31
+ :session_handler, :root_dir, :template_settings, :warmup_urls
32
+ ].each { |key| setting(key) }
33
+
34
+ # Returns a service proc that can be used by the registry.
35
+ #
36
+ # @param [Hash] options
37
+ # @return [Proc]
38
+ def self.service(options = {})
39
+ ->(reg) { new(reg.utils, options) }
40
+ end
49
41
 
50
- def initialize(defaults = {})
51
- defaults[:root_dir] = Dir.pwd unless defaults.key?(:root_dir)
42
+ def initialize(utils, defaults = {})
43
+ @utils = utils
52
44
  super(defaults)
53
45
  end
54
46
 
@@ -66,15 +58,17 @@ module Racket
66
58
  define_method symbol do
67
59
  instance_variable_set(ivar, directory) unless instance_variables.include?(ivar)
68
60
  return nil unless (value = instance_variable_get(ivar))
69
- Utils.build_path(value)
61
+ @utils.build_path(value)
70
62
  end
71
63
  end
72
64
 
73
- directory_setting(:controller_dir, 'controllers')
74
- directory_setting(:helper_dir, 'helpers')
75
- directory_setting(:layout_dir, 'layouts')
76
- directory_setting(:public_dir, 'public')
77
- directory_setting(:view_dir, 'views')
65
+ {
66
+ controller_dir: 'controllers',
67
+ helper_dir: 'helpers',
68
+ layout_dir: 'layouts',
69
+ public_dir: 'public',
70
+ view_dir: 'views'
71
+ }.each_pair { |key, value| directory_setting(key, value) }
78
72
 
79
73
  private_class_method :define_directory_method
80
74
  end
@@ -1,5 +1,5 @@
1
1
  # Racket - The noisy Rack MVC framework
2
- # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
3
  #
4
4
  # This file is part of Racket.
5
5
  #
@@ -36,8 +36,8 @@ module Racket
36
36
  # @param [Symbol] key
37
37
  # @return [nil]
38
38
  def delete(key)
39
- fail ArgumentErrpr,
40
- "Cannot delete standard setting #{key}" if respond_to?(key.to_sym)
39
+ raise ArgumentErrpr,
40
+ "Cannot delete standard setting #{key}" if respond_to?(key.to_sym)
41
41
  @custom.delete(key) && nil
42
42
  end
43
43
 
@@ -68,20 +68,31 @@ module Racket
68
68
  # @param [Object] value
69
69
  # @return [nil]
70
70
  def store(key, value)
71
- fail ArgumentError,
72
- "Cannot overwrite standard setting #{key}" if respond_to?("#{key}=".to_sym)
71
+ raise ArgumentError,
72
+ "Cannot overwrite standard setting #{key}" if respond_to?("#{key}=".to_sym)
73
73
  (@custom[key] = value) && nil
74
74
  end
75
75
 
76
+ # Returns a default value for a key. Default values are stored in @defaults, which is a
77
+ # Racket::Registry object.
78
+ #
79
+ # @param [Symbol] symbol
80
+ # @return [Object]
81
+ def self.default_value(symbol)
82
+ return nil unless defined?(@defaults) && @defaults.respond_to?(symbol)
83
+ @defaults.send(symbol)
84
+ end
85
+
76
86
  # Creates a setting with a default value.
77
87
  #
78
88
  # @param [Symbol] symbol
79
- # @param [Object] default
80
89
  # @return [nil]
81
- def self.setting(symbol, default = nil)
90
+ def self.setting(symbol)
91
+ klass = self
82
92
  ivar = "@#{symbol}".to_sym
83
93
  define_method symbol do
84
- instance_variable_set(ivar, default) unless instance_variables.include?(ivar)
94
+ instance_variable_set(ivar, klass.default_value(symbol)) unless
95
+ instance_variables.include?(ivar)
85
96
  instance_variable_get(ivar)
86
97
  end
87
98
  attr_writer(symbol) && nil