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