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.
- checksums.yaml +4 -4
- data/README.md +7 -5
- data/lib/racket.rb +25 -7
- data/lib/racket/application.rb +70 -136
- data/lib/racket/controller.rb +95 -38
- data/lib/racket/current.rb +1 -1
- data/lib/racket/helpers/file.rb +7 -5
- data/lib/racket/helpers/routing.rb +5 -5
- data/lib/racket/helpers/sass.rb +11 -11
- data/lib/racket/helpers/view.rb +8 -5
- data/lib/racket/plugins/base.rb +1 -1
- data/lib/racket/plugins/sass.rb +1 -1
- data/lib/racket/request.rb +3 -3
- data/lib/racket/response.rb +1 -1
- data/lib/racket/router.rb +31 -12
- data/lib/racket/session.rb +3 -3
- data/lib/racket/settings/application.rb +27 -33
- data/lib/racket/settings/base.rb +19 -8
- data/lib/racket/settings/controller.rb +9 -7
- data/lib/racket/settings/defaults.rb +81 -0
- data/lib/racket/utils.rb +19 -15
- data/lib/racket/utils/application.rb +4 -114
- data/lib/racket/utils/application/handler_stack.rb +163 -0
- data/lib/racket/utils/application/logger.rb +72 -0
- data/lib/racket/utils/application/registry_builder.rb +88 -0
- data/lib/racket/utils/application/stateless_services.rb +73 -0
- data/lib/racket/utils/exceptions.rb +3 -3
- data/lib/racket/utils/file_system.rb +75 -47
- data/lib/racket/utils/helpers.rb +35 -13
- data/lib/racket/utils/routing.rb +62 -46
- data/lib/racket/utils/views.rb +19 -187
- data/lib/racket/utils/views/renderer.rb +75 -0
- data/lib/racket/utils/views/template_cache.rb +126 -0
- data/lib/racket/utils/views/template_locator.rb +83 -0
- data/lib/racket/utils/views/template_resolver.rb +112 -0
- data/lib/racket/version.rb +2 -2
- data/lib/racket/view_manager.rb +12 -4
- data/rake/utils.rb +5 -5
- data/spec/_custom.rb +69 -19
- data/spec/_default.rb +60 -44
- data/spec/_plugin.rb +12 -14
- data/spec/_template_cache.rb +176 -0
- data/spec/racket.rb +10 -13
- data/spec/test_custom_app/controllers/sub1/custom_sub_controller_1.rb +1 -1
- data/spec/test_custom_app/controllers/sub3/custom_sub_controller_3.rb +19 -1
- data/spec/test_custom_app/controllers/sub5/custom_sub_controller_5.rb +8 -0
- data/spec/test_custom_app/files/stuff.rb +3 -0
- data/spec/test_custom_app/files/triplet.erb +5 -0
- data/spec/test_custom_app/templates/sub5/text.erb +3 -0
- data/spec/test_default_app/controllers/default_root_controller.rb +3 -0
- data/spec/test_default_app/controllers/sub1/default_sub_controller_1.rb +1 -1
- 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
|
33
|
-
# object, the
|
34
|
-
# inheritance chain has been queried, the
|
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
|
40
|
-
|
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
|
data/lib/racket/utils.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
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
|