utopia 1.7.1 → 1.8.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/.travis.yml +2 -3
- data/README.md +142 -11
- data/benchmarks/string_vs_symbol.rb +12 -0
- data/lib/utopia/command.rb +16 -13
- data/lib/utopia/content.rb +1 -5
- data/lib/utopia/content/node.rb +9 -4
- data/lib/utopia/{extensions/rack.rb → content/response.rb} +33 -30
- data/lib/utopia/content/tag.rb +14 -17
- data/lib/utopia/content/transaction.rb +19 -17
- data/lib/utopia/controller.rb +29 -8
- data/lib/utopia/controller/actions.rb +148 -0
- data/lib/utopia/controller/base.rb +9 -49
- data/lib/utopia/controller/respond.rb +1 -1
- data/lib/utopia/controller/rewrite.rb +9 -1
- data/lib/utopia/controller/variables.rb +1 -0
- data/lib/utopia/localization.rb +4 -1
- data/lib/utopia/middleware.rb +0 -2
- data/lib/utopia/path.rb +9 -0
- data/lib/utopia/path/matcher.rb +0 -1
- data/lib/utopia/redirection.rb +3 -2
- data/lib/utopia/session.rb +119 -2
- data/lib/utopia/session/lazy_hash.rb +1 -3
- data/lib/utopia/setup.rb +73 -0
- data/lib/utopia/static.rb +9 -2
- data/lib/utopia/version.rb +1 -1
- data/setup/examples/wiki/controller.rb +41 -0
- data/setup/examples/wiki/edit.xnode +15 -0
- data/setup/examples/wiki/index.xnode +10 -0
- data/setup/examples/wiki/welcome/content.md +3 -0
- data/setup/server/config/environment.yaml +1 -0
- data/setup/server/git/hooks/post-receive +4 -5
- data/setup/site/Gemfile +5 -0
- data/setup/site/config.ru +2 -1
- data/setup/site/config/environment.rb +5 -17
- data/setup/site/pages/_page.xnode +4 -2
- data/setup/site/pages/links.yaml +1 -1
- data/setup/site/pages/welcome/index.xnode +33 -15
- data/setup/site/public/_static/site.css +72 -4
- data/setup/site/tasks/utopia.rake +8 -0
- data/spec/utopia/{rack_spec.rb → content/response_spec.rb} +12 -19
- data/spec/utopia/content_spec.rb +2 -3
- data/spec/utopia/controller/{action_spec.rb → actions_spec.rb} +18 -32
- data/spec/utopia/controller/middleware_spec.rb +10 -10
- data/spec/utopia/controller/middleware_spec/controller/controller.rb +3 -3
- data/spec/utopia/controller/middleware_spec/controller/nested/controller.rb +1 -1
- data/spec/utopia/controller/middleware_spec/redirect/controller.rb +1 -1
- data/spec/utopia/controller/respond_spec.rb +3 -2
- data/spec/utopia/controller/respond_spec/api/controller.rb +2 -2
- data/spec/utopia/controller/respond_spec/errors/controller.rb +1 -1
- data/spec/utopia/controller/rewrite_spec.rb +1 -1
- data/spec/utopia/controller/sequence_spec.rb +12 -16
- data/spec/utopia/exceptions/handler_spec/controller.rb +2 -2
- data/spec/utopia/performance_spec/config.ru +1 -0
- data/spec/utopia/session_spec.rb +34 -1
- data/spec/utopia/session_spec.ru +3 -3
- data/spec/utopia/setup_spec.rb +2 -2
- data/utopia.gemspec +2 -2
- metadata +18 -12
- data/lib/utopia/controller/action.rb +0 -116
- data/lib/utopia/session/encrypted_cookie.rb +0 -118
data/lib/utopia/content/tag.rb
CHANGED
@@ -56,52 +56,49 @@ module Utopia
|
|
56
56
|
def [](key)
|
57
57
|
@attributes[key]
|
58
58
|
end
|
59
|
-
|
60
|
-
def to_html(content = nil, buffer = StringIO.new)
|
61
|
-
write_full_html(buffer, content)
|
62
|
-
|
63
|
-
return buffer.string
|
64
|
-
end
|
65
59
|
|
66
60
|
def to_hash
|
67
61
|
@attributes
|
68
62
|
end
|
69
63
|
|
70
64
|
def to_s(content = nil)
|
71
|
-
buffer =
|
65
|
+
buffer = String.new
|
66
|
+
|
72
67
|
write_full_html(buffer, content)
|
73
|
-
|
68
|
+
|
69
|
+
return buffer
|
74
70
|
end
|
75
71
|
|
72
|
+
alias to_html to_s
|
73
|
+
|
76
74
|
def write_open_html(buffer, terminate = false)
|
77
|
-
buffer
|
78
|
-
buffer.write "<#{name}"
|
75
|
+
buffer << "<#{name}"
|
79
76
|
|
80
77
|
@attributes.each do |key, value|
|
81
78
|
if value
|
82
|
-
buffer
|
79
|
+
buffer << " #{key}=\"#{value}\""
|
83
80
|
else
|
84
|
-
buffer
|
81
|
+
buffer << " #{key}"
|
85
82
|
end
|
86
83
|
end
|
87
84
|
|
88
85
|
if terminate
|
89
|
-
buffer
|
86
|
+
buffer << "/>"
|
90
87
|
else
|
91
|
-
buffer
|
88
|
+
buffer << ">"
|
92
89
|
end
|
93
90
|
end
|
94
91
|
|
95
92
|
def write_close_html(buffer)
|
96
|
-
buffer
|
93
|
+
buffer << "</#{name}>"
|
97
94
|
end
|
98
95
|
|
99
96
|
def write_full_html(buffer, content = nil)
|
100
|
-
if @closed
|
97
|
+
if @closed and content.nil?
|
101
98
|
write_open_html(buffer, true)
|
102
99
|
else
|
103
100
|
write_open_html(buffer)
|
104
|
-
buffer
|
101
|
+
buffer << content if content
|
105
102
|
write_close_html(buffer)
|
106
103
|
end
|
107
104
|
end
|
@@ -20,6 +20,8 @@
|
|
20
20
|
|
21
21
|
require_relative 'links'
|
22
22
|
|
23
|
+
require_relative 'response'
|
24
|
+
|
23
25
|
module Utopia
|
24
26
|
class Content
|
25
27
|
# This error is thrown if a tag doesn't match up when parsing the
|
@@ -37,19 +39,21 @@ module Utopia
|
|
37
39
|
CONTENT_TAG_NAME = "content".freeze
|
38
40
|
|
39
41
|
# A single request through content middleware. We use a struct to hide instance varibles since we instance_exec within this context.
|
40
|
-
class Transaction
|
41
|
-
|
42
|
-
|
43
|
-
def initialize(request, response, attributes = {})
|
42
|
+
class Transaction < Response
|
43
|
+
def initialize(request, attributes = {})
|
44
44
|
@request = request
|
45
|
-
@response = response
|
46
45
|
|
47
46
|
@attributes = attributes
|
48
47
|
|
49
48
|
@begin_tags = []
|
50
49
|
@end_tags = []
|
50
|
+
|
51
|
+
super()
|
51
52
|
end
|
52
53
|
|
54
|
+
attr :status
|
55
|
+
attr :headers
|
56
|
+
|
53
57
|
# A helper method for accessing controller variables from view:
|
54
58
|
def controller
|
55
59
|
@controller ||= Utopia::Controller[request]
|
@@ -66,9 +70,6 @@ module Utopia
|
|
66
70
|
# The Rack::Request for this transaction.
|
67
71
|
attr :request
|
68
72
|
|
69
|
-
# The mutable Rack::Response for this transaction.
|
70
|
-
attr :response
|
71
|
-
|
72
73
|
# Per-transaction global attributes.
|
73
74
|
attr :attributes
|
74
75
|
|
@@ -133,7 +134,6 @@ module Utopia
|
|
133
134
|
# Get the current tag which we are completing/ending:
|
134
135
|
top = current
|
135
136
|
|
136
|
-
|
137
137
|
if top.tags.empty?
|
138
138
|
if top.node.respond_to? :tag_end
|
139
139
|
top.node.tag_end(self, top)
|
@@ -156,7 +156,7 @@ module Utopia
|
|
156
156
|
|
157
157
|
return nil
|
158
158
|
end
|
159
|
-
|
159
|
+
|
160
160
|
def render_node(node, attributes = {})
|
161
161
|
self.begin_tags << State.new(attributes, node)
|
162
162
|
|
@@ -206,8 +206,10 @@ module Utopia
|
|
206
206
|
class Transaction::State
|
207
207
|
def initialize(tag, node, attributes = tag.to_hash)
|
208
208
|
@node = node
|
209
|
-
|
210
|
-
|
209
|
+
|
210
|
+
# The contents of the output
|
211
|
+
@buffer = String.new
|
212
|
+
|
211
213
|
@overrides = {}
|
212
214
|
|
213
215
|
@tags = []
|
@@ -228,7 +230,7 @@ module Utopia
|
|
228
230
|
def defer(value = nil, &block)
|
229
231
|
@deferred << block
|
230
232
|
|
231
|
-
Tag.closed(DEFERRED_TAG_NAME, :id => @deferred.size - 1).
|
233
|
+
Tag.closed(DEFERRED_TAG_NAME, :id => @deferred.size - 1).to_s
|
232
234
|
end
|
233
235
|
|
234
236
|
def [](key)
|
@@ -250,8 +252,8 @@ module Utopia
|
|
250
252
|
end
|
251
253
|
|
252
254
|
def call(transaction)
|
253
|
-
@content = @buffer
|
254
|
-
@buffer =
|
255
|
+
@content = @buffer
|
256
|
+
@buffer = String.new
|
255
257
|
|
256
258
|
if node.respond_to? :call
|
257
259
|
node.call(transaction, self)
|
@@ -259,11 +261,11 @@ module Utopia
|
|
259
261
|
transaction.parse_markup(@content)
|
260
262
|
end
|
261
263
|
|
262
|
-
return @buffer
|
264
|
+
return @buffer
|
263
265
|
end
|
264
266
|
|
265
267
|
def cdata(text)
|
266
|
-
@buffer
|
268
|
+
@buffer << text
|
267
269
|
end
|
268
270
|
|
269
271
|
def markup(text)
|
data/lib/utopia/controller.rb
CHANGED
@@ -22,15 +22,16 @@ require_relative 'path'
|
|
22
22
|
|
23
23
|
require_relative 'middleware'
|
24
24
|
require_relative 'controller/variables'
|
25
|
-
require_relative 'controller/action'
|
26
25
|
require_relative 'controller/base'
|
27
26
|
|
28
27
|
require_relative 'controller/rewrite'
|
29
28
|
require_relative 'controller/respond'
|
29
|
+
require_relative 'controller/actions'
|
30
30
|
|
31
31
|
require 'concurrent/map'
|
32
32
|
|
33
33
|
module Utopia
|
34
|
+
# A container for controller classes which are loaded from disk.
|
34
35
|
module Controllers
|
35
36
|
def self.class_name_for_controller(controller)
|
36
37
|
controller.uri_path.to_a.collect{|_| _.capitalize}.join + "_#{controller.object_id}"
|
@@ -44,14 +45,16 @@ module Utopia
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
# A middleware which loads controller classes and invokes functionality based on the requested path.
|
47
49
|
class Controller
|
50
|
+
# The controller filename.
|
48
51
|
CONTROLLER_RB = 'controller.rb'.freeze
|
49
52
|
|
50
53
|
def self.[] request
|
51
54
|
request.env[VARIABLES_KEY]
|
52
55
|
end
|
53
56
|
|
54
|
-
def initialize(app, root: nil, cache_controllers: false)
|
57
|
+
def initialize(app, root: nil, cache_controllers: false, base: nil)
|
55
58
|
@app = app
|
56
59
|
@root = root || Utopia::default_root
|
57
60
|
|
@@ -60,6 +63,10 @@ module Utopia
|
|
60
63
|
else
|
61
64
|
@controller_cache = nil
|
62
65
|
end
|
66
|
+
|
67
|
+
warn "Controller middleware is automatically prepending Actions! Will be deprecated in 2.x" if $VERBOSE and base.nil?
|
68
|
+
|
69
|
+
@base = base || Controller::Base.dup.prepend(Controller::Actions)
|
63
70
|
end
|
64
71
|
|
65
72
|
attr :app
|
@@ -67,9 +74,13 @@ module Utopia
|
|
67
74
|
def freeze
|
68
75
|
@root.freeze
|
69
76
|
|
77
|
+
# Should we freeze the base class?
|
78
|
+
# @base.freeze
|
79
|
+
|
70
80
|
super
|
71
81
|
end
|
72
82
|
|
83
|
+
# Fetch the controller for the given relative path. May be cached.
|
73
84
|
def lookup_controller(path)
|
74
85
|
if @controller_cache
|
75
86
|
@controller_cache.fetch_or_store(path.to_s) do
|
@@ -80,6 +91,7 @@ module Utopia
|
|
80
91
|
end
|
81
92
|
end
|
82
93
|
|
94
|
+
# Loads the controller file for the given relative url_path.
|
83
95
|
def load_controller_file(uri_path)
|
84
96
|
base_path = File.join(@root, uri_path.components)
|
85
97
|
|
@@ -87,7 +99,7 @@ module Utopia
|
|
87
99
|
# puts "load_controller_file(#{path.inspect}) => #{controller_path}"
|
88
100
|
|
89
101
|
if File.exist?(controller_path)
|
90
|
-
klass = Class.new(
|
102
|
+
klass = Class.new(@base)
|
91
103
|
|
92
104
|
# base_path is expected to be a string representing a filesystem path:
|
93
105
|
klass.const_set(:BASE_PATH, base_path.freeze)
|
@@ -112,13 +124,22 @@ module Utopia
|
|
112
124
|
end
|
113
125
|
end
|
114
126
|
|
127
|
+
# Invoke the controller layer for a given request. The request path may be rewritten.
|
115
128
|
def invoke_controllers(request)
|
116
|
-
|
129
|
+
request_path = Path.from_string(request.path_info)
|
130
|
+
|
131
|
+
# The request path must be absolute. We could handle this internally but it is probably better for this to be an error:
|
132
|
+
raise ArgumentError.new("Invalid request path #{request_path}") unless request_path.absolute?
|
133
|
+
|
134
|
+
# The controller path contains the current complete path being evaluated:
|
117
135
|
controller_path = Path.new
|
136
|
+
|
137
|
+
# Controller instance variables which eventually get processed by the view:
|
118
138
|
variables = request.env[VARIABLES_KEY]
|
119
139
|
|
120
|
-
while
|
121
|
-
|
140
|
+
while request_path.components.any?
|
141
|
+
# We copy one path component from the relative path to the controller path at a time. The controller, when invoked, can modify the relative path (by assigning to relative_path.components). This allows for controller-relative rewrites, but only the remaining path postfix can be modified.
|
142
|
+
controller_path.components << request_path.components.shift
|
122
143
|
|
123
144
|
if controller = lookup_controller(controller_path)
|
124
145
|
# Don't modify the original controller:
|
@@ -127,13 +148,13 @@ module Utopia
|
|
127
148
|
# Append the controller to the set of controller variables, updates the controller with all current instance variables.
|
128
149
|
variables << controller
|
129
150
|
|
130
|
-
if result = controller.process!(request,
|
151
|
+
if result = controller.process!(request, request_path)
|
131
152
|
return result
|
132
153
|
end
|
133
154
|
end
|
134
155
|
end
|
135
156
|
|
136
|
-
# The controllers may have rewriten the path so we update the path info:
|
157
|
+
# Controllers can directly modify relative_path, which is copied into controller_path. The controllers may have rewriten the path so we update the path info:
|
137
158
|
request.env[Rack::PATH_INFO] = controller_path.to_s
|
138
159
|
|
139
160
|
# No controller gave a useful result:
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require_relative '../http'
|
22
|
+
|
23
|
+
module Utopia
|
24
|
+
class Controller
|
25
|
+
module Actions
|
26
|
+
def self.prepended(base)
|
27
|
+
base.extend(ClassMethods)
|
28
|
+
end
|
29
|
+
|
30
|
+
class Action < Hash
|
31
|
+
def initialize(options = {}, &block)
|
32
|
+
@options = options
|
33
|
+
@callback = block
|
34
|
+
|
35
|
+
super()
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :callback, :options
|
39
|
+
|
40
|
+
def callback?
|
41
|
+
@callback != nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def eql? other
|
45
|
+
super and @callback.eql? other.callback and @options.eql? other.options
|
46
|
+
end
|
47
|
+
|
48
|
+
def hash
|
49
|
+
[super, @callback, @options].hash
|
50
|
+
end
|
51
|
+
|
52
|
+
def == other
|
53
|
+
super and @callback == other.callback and @options == other.options
|
54
|
+
end
|
55
|
+
|
56
|
+
WILDCARD_GREEDY = '**'.freeze
|
57
|
+
WILDCARD = '*'.freeze
|
58
|
+
|
59
|
+
# Given a path, iterate over all actions that match. Actions match from most specific to most general.
|
60
|
+
# @return nil if nothing matched, or true if something matched.
|
61
|
+
def apply(path, index = -1, &block)
|
62
|
+
# ** is greedy, it always matches if possible and matches all remaining input.
|
63
|
+
if match_all = self[WILDCARD_GREEDY] and match_all.callback?
|
64
|
+
matched = true; yield(match_all)
|
65
|
+
end
|
66
|
+
|
67
|
+
if name = path[index]
|
68
|
+
# puts "Matching #{name} in #{self.keys.inspect}"
|
69
|
+
|
70
|
+
if match_name = self[name]
|
71
|
+
# puts "Matched against exact name #{name}: #{match_name}"
|
72
|
+
matched = match_name.apply(path, index-1, &block) || matched
|
73
|
+
end
|
74
|
+
|
75
|
+
if match_one = self[WILDCARD]
|
76
|
+
# puts "Match against #{WILDCARD}: #{match_one}"
|
77
|
+
matched = match_one.apply(path, index-1, &block) || matched
|
78
|
+
end
|
79
|
+
elsif self.callback?
|
80
|
+
# Got to end, matched completely:
|
81
|
+
matched = true; yield(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
return matched
|
85
|
+
end
|
86
|
+
|
87
|
+
def matching(path, &block)
|
88
|
+
to_enum(:apply, path).to_a
|
89
|
+
end
|
90
|
+
|
91
|
+
def define(path, **options, &callback)
|
92
|
+
# puts "Defining path: #{path.inspect}"
|
93
|
+
current = self
|
94
|
+
|
95
|
+
path.reverse_each do |name|
|
96
|
+
current = (current[name] ||= Action.new)
|
97
|
+
end
|
98
|
+
|
99
|
+
current.options = options
|
100
|
+
current.callback = callback
|
101
|
+
|
102
|
+
return current
|
103
|
+
end
|
104
|
+
|
105
|
+
def inspect
|
106
|
+
if callback?
|
107
|
+
"<action " + super + ":#{callback.source_location}(#{options})>"
|
108
|
+
else
|
109
|
+
"<action " + super + ">"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module ClassMethods
|
115
|
+
def actions
|
116
|
+
@actions ||= Action.new
|
117
|
+
end
|
118
|
+
|
119
|
+
def on(first, *path, **options, &block)
|
120
|
+
if first.is_a? Symbol
|
121
|
+
first = ['**', first.to_s]
|
122
|
+
end
|
123
|
+
|
124
|
+
actions.define(Path.split(first) + path, options, &block)
|
125
|
+
end
|
126
|
+
|
127
|
+
def dispatch(controller, request, path)
|
128
|
+
if @actions
|
129
|
+
@actions.apply(path.components) do |action|
|
130
|
+
controller.instance_exec(request, path, &action.callback)
|
131
|
+
end || controller.otherwise(request, path)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def otherwise(request, path)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Given a request, call associated actions if at least one exists.
|
140
|
+
def process!(request, path)
|
141
|
+
# puts "Actions\#process!(..., #{path.inspect})"
|
142
|
+
catch_response do
|
143
|
+
self.class.dispatch(self, request, path)
|
144
|
+
end || super
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -23,14 +23,17 @@ require_relative '../http'
|
|
23
23
|
module Utopia
|
24
24
|
class Controller
|
25
25
|
class Base
|
26
|
+
# A string which is the full path to the directory which contains the controller.
|
26
27
|
def self.base_path
|
27
28
|
self.const_get(:BASE_PATH)
|
28
29
|
end
|
29
|
-
|
30
|
+
|
31
|
+
# A relative path to the controller directory relative to the controller root directory.
|
30
32
|
def self.uri_path
|
31
33
|
self.const_get(:URI_PATH)
|
32
34
|
end
|
33
|
-
|
35
|
+
|
36
|
+
# The controller middleware itself.
|
34
37
|
def self.controller
|
35
38
|
self.const_get(:CONTROLLER)
|
36
39
|
end
|
@@ -48,32 +51,6 @@ module Utopia
|
|
48
51
|
def direct?(path)
|
49
52
|
path.dirname == uri_path
|
50
53
|
end
|
51
|
-
|
52
|
-
def actions
|
53
|
-
@actions ||= Action.new
|
54
|
-
end
|
55
|
-
|
56
|
-
def on(first, *path, **options, &block)
|
57
|
-
if first.is_a? Symbol
|
58
|
-
first = ['**', first]
|
59
|
-
end
|
60
|
-
|
61
|
-
actions.define(Path.split(first) + path, options, &block)
|
62
|
-
end
|
63
|
-
|
64
|
-
def lookup(path)
|
65
|
-
if @actions
|
66
|
-
relative_path = (path - uri_path).to_a
|
67
|
-
return @actions.select(relative_path)
|
68
|
-
else
|
69
|
-
[]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Given a path, look up all matched actions.
|
75
|
-
def actions_for_request(request, path)
|
76
|
-
self.class.lookup(path)
|
77
54
|
end
|
78
55
|
|
79
56
|
def catch_response
|
@@ -82,18 +59,8 @@ module Utopia
|
|
82
59
|
end
|
83
60
|
end
|
84
61
|
|
85
|
-
#
|
86
|
-
def
|
87
|
-
actions = actions_for_request(request, path)
|
88
|
-
|
89
|
-
unless actions.empty?
|
90
|
-
return catch_response do
|
91
|
-
actions.each do |action|
|
92
|
-
action.call(self, request, path)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
62
|
+
# Return nil if this controller didn't do anything. Request will keep on processing. Return a valid rack response if the controller can do so.
|
63
|
+
def process!(request, relative_path)
|
97
64
|
return nil
|
98
65
|
end
|
99
66
|
|
@@ -114,7 +81,7 @@ module Utopia
|
|
114
81
|
throw :response, response
|
115
82
|
end
|
116
83
|
|
117
|
-
|
84
|
+
# This will cause the controller middleware to pass on the request.
|
118
85
|
def ignore!
|
119
86
|
throw :response, nil
|
120
87
|
end
|
@@ -140,6 +107,7 @@ module Utopia
|
|
140
107
|
respond! [status.to_i, {}, [message]]
|
141
108
|
end
|
142
109
|
|
110
|
+
# Succeed the request and immediately respond.
|
143
111
|
def succeed!(status: 200, headers: {}, **options)
|
144
112
|
status = HTTP::Status.new(status, 200...300)
|
145
113
|
|
@@ -159,14 +127,6 @@ module Utopia
|
|
159
127
|
return [content]
|
160
128
|
end
|
161
129
|
end
|
162
|
-
|
163
|
-
# Legacy method name:
|
164
|
-
alias success! succeed!
|
165
|
-
|
166
|
-
# Return nil if this controller didn't do anything. Request will keep on processing. Return a valid rack response if the controller can do so.
|
167
|
-
def process!(request, path)
|
168
|
-
passthrough(request, path)
|
169
|
-
end
|
170
130
|
end
|
171
131
|
end
|
172
132
|
end
|