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
  #
@@ -29,15 +29,17 @@ module Racket
29
29
  @owner = owner
30
30
  end
31
31
 
32
- # Fetches settings from the current object. If the setting cannot be found in the Current
33
- # object, the controller superklass will be queried. If all controller classes in the
34
- # inheritance chain has been queried, the Application settings will be used as a final
32
+ # Fetches settings from the current object. If the setting cannot be found in the current
33
+ # object, the objects class/superclass will be queried. If all controller classes in the
34
+ # inheritance chain has been queried, the application settings will be used as a final
35
35
  # fallback.
36
36
  def fetch(key, default = nil)
37
37
  return @custom[key] if @custom.key?(key)
38
- parent = @owner.superclass
39
- return ::Racket::Application.settings.fetch(key, default) if
40
- [@owner, parent].include?(::Racket::Controller)
38
+ parent = @owner.is_a?(Class) ? @owner.superclass : @owner.class
39
+ return @owner.context.application_settings.fetch(key, default) if
40
+ @owner == ::Racket::Controller
41
+ return parent.context.application_settings.fetch(key, default) if
42
+ parent == ::Racket::Controller
41
43
  parent.settings.fetch(key, default)
42
44
  end
43
45
  end
@@ -0,0 +1,81 @@
1
+ # Racket - The noisy Rack MVC framework
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
+ #
4
+ # This file is part of Racket.
5
+ #
6
+ # Racket is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Racket is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'logger'
20
+ require 'racket/registry'
21
+
22
+ module Racket
23
+ module Settings
24
+ # Module used for storing default values.
25
+ module Defaults
26
+ # Returns a Racke::Registry object containing application defaults.
27
+ #
28
+ # @return [Racket::Registry]
29
+ def self.application_defaults
30
+ Racket::Registry.with_map(
31
+ default_action: -> { :index },
32
+ default_content_type: -> { 'text/html' },
33
+ default_controller_helpers: -> { [:routing, :view] },
34
+ default_layout: nil_block,
35
+ default_view: nil_block,
36
+ logger: -> { Logger.new($stdout) },
37
+ middleware: array_block,
38
+ mode: -> { :live },
39
+ plugins: array_block,
40
+ session_handler: session_handler,
41
+ root_dir: -> { Dir.pwd },
42
+ template_settings: template_settings,
43
+ warmup_urls: -> { Set.new }
44
+ )
45
+ end
46
+
47
+ def self.array_block
48
+ -> { [] }
49
+ end
50
+
51
+ def self.nil_block
52
+ -> { nil }
53
+ end
54
+
55
+ def self.session_handler
56
+ lambda do
57
+ [
58
+ Rack::Session::Cookie,
59
+ {
60
+ key: 'racket.session',
61
+ old_secret: SecureRandom.hex(16),
62
+ secret: SecureRandom.hex(16)
63
+ }
64
+ ]
65
+ end
66
+ end
67
+
68
+ def self.template_settings
69
+ lambda do
70
+ {
71
+ common: {},
72
+ layout: {},
73
+ view: {}
74
+ }
75
+ end
76
+ end
77
+
78
+ private_class_method :array_block, :nil_block, :session_handler, :template_settings
79
+ end
80
+ end
81
+ 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,21 +26,25 @@ require_relative 'utils/views.rb'
26
26
  module Racket
27
27
  # Collects utilities needed by different objects in Racket.
28
28
  module Utils
29
- extend SingleForwardable
29
+ # Collects functionality from all utility modules into a handy class.
30
+ class ToolBelt
31
+ include Application
32
+ include Exceptions
33
+ include FileSystem
34
+ include Helpers
35
+ include Views
30
36
 
31
- # Embraces a module, making its class methods available as class methods on the current module.
32
- #
33
- # @param [Module] mod
34
- # @return [nil]
35
- def self.__embrace(mod)
36
- def_single_delegators(mod, *mod.singleton_methods) && nil
37
- end
37
+ # Returns a service proc that can be used by the registry.
38
+ #
39
+ # @param [Hash] options
40
+ # @return [Proc]
41
+ def self.service(options = {})
42
+ -> { new(options[:root_dir]) }
43
+ end
38
44
 
39
- __embrace(Application)
40
- __embrace(Exceptions)
41
- __embrace(FileSystem)
42
- __embrace(Helpers)
43
- __embrace(Routing)
44
- __embrace(Views)
45
+ def initialize(root_dir)
46
+ @root_dir = Pathname.new(root_dir).cleanpath.expand_path
47
+ end
48
+ end
45
49
  end
46
50
  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,116 +16,6 @@
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
- module Racket
20
- # Collects utilities needed by different objects in Racket.
21
- module Utils
22
- # Utility functions for filesystem.
23
- module Application
24
- # Class used for building a proper Rack application.
25
- class ApplicationBuilder
26
- def initialize(application)
27
- @application = application
28
- @builder = Rack::Builder.new
29
- @settings = @application.settings
30
- @middleware = @settings.middleware
31
- end
32
-
33
- # Builds a Rack application representing Racket.
34
- #
35
- # @return [Proc]
36
- def build
37
- init_plugins
38
- add_warmup_hook
39
- add_middleware
40
- @builder.run(application_proc)
41
- @builder
42
- end
43
-
44
- private
45
-
46
- # Add middleware to the builder.
47
- def add_middleware
48
- expand_middleware_list
49
- @middleware.each do |ware|
50
- klass, opts = ware
51
- @application.inform_dev("Loading middleware #{klass} with settings #{opts.inspect}.")
52
- @builder.use(*ware)
53
- end
54
- end
55
-
56
- # Add a list of urls to visit on startup
57
- def add_warmup_hook
58
- warmup_urls = Racket::Application.settings.warmup_urls
59
- return if warmup_urls.empty?
60
- @builder.warmup do |app|
61
- client = Rack::MockRequest.new(app)
62
- visit_warmup_urls(client, warmup_urls)
63
- end
64
- end
65
-
66
- # Returns a lambda that represenents that application flow.
67
- def application_proc
68
- application = @application
69
- lambda do |env|
70
- static_result = application.serve_static_file(env)
71
- return static_result if static_result && static_result.first < 400
72
- application.router.route(env)
73
- end
74
- end
75
-
76
- # Expands middleware list based on application settings.
77
- def expand_middleware_list
78
- session_handler = @settings.session_handler
79
- default_content_type = @settings.default_content_type
80
- @middleware.unshift(session_handler) if session_handler
81
- @middleware.unshift([Rack::ContentType, default_content_type]) if default_content_type
82
- @middleware.unshift([Rack::ShowExceptions]) if @application.dev_mode?
83
- end
84
-
85
- # Initializes plugins.
86
- def init_plugins
87
- @settings.plugins.each do |plugin_info|
88
- plugin_instance = self.class.get_plugin_instance(*plugin_info)
89
- run_plugin_hooks(plugin_instance)
90
- # TODO: Store plugin instance somewhere in application settings
91
- end
92
- end
93
-
94
- # Runs plugin hooks.
95
- def run_plugin_hooks(plugin_obj)
96
- @middleware.concat(plugin_obj.middleware)
97
- @settings.default_controller_helpers.concat(plugin_obj.default_controller_helpers)
98
- end
99
-
100
- # Visits a list of warmup URLs.
101
- def visit_warmup_urls(client, urls)
102
- urls.each do |url|
103
- @application.inform_dev("Visiting warmup url #{url}.")
104
- client.get(url)
105
- end
106
- end
107
-
108
- # Returns an instance of a specific plugin.
109
- #
110
- # @param [Symbol] plugin
111
- # @param [Hash|nil] settings
112
- # @return [Object] An instance of the requested plugin class
113
- def self.get_plugin_instance(plugin, settings)
114
- Utils.safe_require("racket/plugins/#{plugin}.rb")
115
- # TODO: Allow custom plugins dir as well
116
- klass =
117
- Racket::Plugins.const_get(plugin.to_s.split('_').collect(&:capitalize).join.to_sym)
118
- klass.new(settings)
119
- end
120
- end
121
-
122
- # Builds and returns a Rack::Builder using the provided Racket::Application
123
- #
124
- # @param [Racket::Application] application
125
- # @return [Rack::Builder]
126
- def self.build_application(application)
127
- ApplicationBuilder.new(application).build
128
- end
129
- end
130
- end
131
- end
19
+ require_relative 'application/handler_stack.rb'
20
+ require_relative 'application/logger.rb'
21
+ require_relative 'application/registry_builder.rb'
@@ -0,0 +1,163 @@
1
+ # Racket - The noisy Rack MVC framework
2
+ # Copyright (C) 2015-2016 Lars Olsson <lasso@lassoweb.se>
3
+ #
4
+ # This file is part of Racket.
5
+ #
6
+ # Racket is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Racket is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require 'ostruct'
20
+
21
+ module Racket
22
+ module Utils
23
+ module Application
24
+ # Class used for building a proper Rack application.
25
+ class HandlerStack
26
+ attr_reader :stack
27
+
28
+ # Returns a service proc that can be used by the registry.
29
+ #
30
+ # @param [Hash] _options (unused)
31
+ # @return [Proc]
32
+ def self.service(_options = {})
33
+ lambda do |reg|
34
+ settings = reg.application_settings
35
+
36
+ options = {
37
+ default_content_type: settings.default_content_type,
38
+ default_controller_helpers: settings.default_controller_helpers,
39
+ dev_mode: settings.mode == :dev,
40
+ logger: reg.application_logger,
41
+ middleware: settings.middleware,
42
+ plugins: settings.plugins,
43
+ router: reg.router,
44
+ session_handler: settings.session_handler,
45
+ static_server: reg.static_server,
46
+ utils: reg.utils,
47
+ warmup_urls: settings.warmup_urls
48
+ }
49
+
50
+ new(options).stack
51
+ end
52
+ end
53
+
54
+ def initialize(options)
55
+ @stack = Rack::Builder.new
56
+ @options = OpenStruct.new(options)
57
+ build
58
+ end
59
+
60
+ private
61
+
62
+ # Builds a Rack application representing Racket.
63
+ #
64
+ # @return [Proc]
65
+ def build
66
+ init_plugins
67
+ add_warmup_hook
68
+ add_middleware(@options.middleware)
69
+ @stack.run(application_proc)
70
+ end
71
+
72
+ # Add middleware to the builder.
73
+ def add_middleware(middleware)
74
+ expand_middleware_list(middleware)
75
+ middleware.each do |ware|
76
+ klass, opts = ware
77
+ @options.logger.inform_dev("Loading middleware #{klass} with settings #{opts.inspect}.")
78
+ @stack.use(*ware)
79
+ end
80
+ end
81
+
82
+ # Add a list of urls to visit on startup
83
+ def add_warmup_hook
84
+ warmup_urls = @options.warmup_urls
85
+ return if warmup_urls.empty?
86
+ @stack.warmup do |app|
87
+ client = Rack::MockRequest.new(app)
88
+ visit_warmup_urls(client, warmup_urls)
89
+ end
90
+ end
91
+
92
+ # Returns a lambda that represenents that application flow.
93
+ def application_proc
94
+ if (static_server = @options.static_server)
95
+ application_proc_with_static_server(static_server)
96
+ else
97
+ application_proc_without_static_server
98
+ end
99
+ end
100
+
101
+ def application_proc_with_static_server(static_server)
102
+ router = @options.router
103
+ lambda do |env|
104
+ static_result = static_server.call(env)
105
+ return static_result if static_result && static_result.first < 400
106
+ router.route(env)
107
+ end
108
+ end
109
+
110
+ def application_proc_without_static_server
111
+ router = @options.router
112
+ ->(env) { router.route(env) }
113
+ end
114
+
115
+ # Expands middleware list based on application settings.
116
+ def expand_middleware_list(middleware)
117
+ session_handler = @options.session_handler
118
+ default_content_type = @options.default_content_type
119
+ middleware.unshift(session_handler) if session_handler
120
+ middleware.unshift([Rack::ContentType, default_content_type]) if
121
+ default_content_type
122
+ middleware.unshift([Rack::ShowExceptions]) if @options.dev_mode
123
+ end
124
+
125
+ # Returns an instance of a specific plugin.
126
+ #
127
+ # @param [Symbol] plugin
128
+ # @param [Hash|nil] settings
129
+ # @return [Object] An instance of the requested plugin class
130
+ def get_plugin_instance(plugin, settings)
131
+ @options.utils.safe_require("racket/plugins/#{plugin}.rb")
132
+ # TODO: Allow custom plugins dir as well
133
+ klass =
134
+ Racket::Plugins.const_get(plugin.to_s.split('_').collect(&:capitalize).join.to_sym)
135
+ klass.new(settings)
136
+ end
137
+
138
+ # Initializes plugins.
139
+ def init_plugins
140
+ @options.plugins.each do |plugin_info|
141
+ plugin_instance = get_plugin_instance(*plugin_info)
142
+ run_plugin_hooks(plugin_instance)
143
+ # TODO: Store plugin instance somewhere in application settings
144
+ end
145
+ end
146
+
147
+ # Runs plugin hooks.
148
+ def run_plugin_hooks(plugin_obj)
149
+ @options.middleware.concat(plugin_obj.middleware)
150
+ @options.default_controller_helpers.concat(plugin_obj.default_controller_helpers)
151
+ end
152
+
153
+ # Visits a list of warmup URLs.
154
+ def visit_warmup_urls(client, urls)
155
+ urls.each do |url|
156
+ @options.logger.inform_dev("Visiting warmup url #{url}.")
157
+ client.get(url)
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end