racket-mvc 0.4.0 → 0.5.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.
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