roda 3.67.0 → 3.69.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/CHANGELOG +8 -0
- data/doc/release_notes/3.68.0.txt +21 -0
- data/doc/release_notes/3.69.0.txt +33 -0
- data/lib/roda/plugins/class_matchers.rb +1 -1
- data/lib/roda/plugins/multi_run.rb +51 -17
- data/lib/roda/plugins/symbol_matchers.rb +36 -5
- data/lib/roda/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2871ec8db3a18a77238fdae1aeb786c7a7eb93f14b0827428fab1b07f6e7bee8
|
|
4
|
+
data.tar.gz: 75db2ec79978055f407c2270cfd9119782322402c2c536a504fbfc08f4fedac7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ca4fdcac9bcba88309b8ccb4315ea2243530b08313135f97a643b81600b98821521fbbe08e9c7ab757732887326e8af492f0f3e883a3f54e7be73f0811d19e6
|
|
7
|
+
data.tar.gz: 6b313eecbd4f62d07bca53fa23db2325b4f53f3faf55344c86d8f543ff92c5dcba94235f963582ce227d3602e3ea8633e981393ef6aedcbe20fb8152e6409c08
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
= 3.69.0 (2023-06-13)
|
|
2
|
+
|
|
3
|
+
* Allow symbol_matcher in symbol_matchers plugin to take a block to allow type conversion (jeremyevans)
|
|
4
|
+
|
|
5
|
+
= 3.68.0 (2023-05-11)
|
|
6
|
+
|
|
7
|
+
* Make Roda.run in multi_run plugin accept blocks to allow autoloading the apps to dispatch to (jeremyevans)
|
|
8
|
+
|
|
1
9
|
= 3.67.0 (2023-04-12)
|
|
2
10
|
|
|
3
11
|
* Add custom_block_results plugin for registering custom block result handlers (jeremyevans)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
= New Feature
|
|
2
|
+
|
|
3
|
+
* Roda.run in the multi_run plugin now accepts blocks, to allow
|
|
4
|
+
autoloading of apps to dispatch to:
|
|
5
|
+
|
|
6
|
+
class App < Roda
|
|
7
|
+
plugin :multi_run
|
|
8
|
+
|
|
9
|
+
run("other_app"){OtherApp}
|
|
10
|
+
|
|
11
|
+
route do |r|
|
|
12
|
+
r.multi_run
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
With the above example, the block is not evaluated until a
|
|
17
|
+
request for the /other_app branch is received. If OtherApp is
|
|
18
|
+
autoloaded, this can speed up application startup and partial
|
|
19
|
+
testing. When freezing the application (for production use),
|
|
20
|
+
the block is eagerly loaded, so that requests to the
|
|
21
|
+
/other_app branch do not call the block on every request.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
= New Feature
|
|
2
|
+
|
|
3
|
+
* The symbol_matcher method in the symbol_matchers plugin now
|
|
4
|
+
supports a block to allow for type conversion of matched
|
|
5
|
+
segments:
|
|
6
|
+
|
|
7
|
+
symbol_matcher(:date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
|
|
8
|
+
[Date.new(y.to_i, m.to_i, d.to_i)]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
route do |r|
|
|
12
|
+
r.on :date do |date|
|
|
13
|
+
# date is an instance of Date
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
As shown above, the block should return an array of objects to yield
|
|
18
|
+
to the match block.
|
|
19
|
+
|
|
20
|
+
If you have a segment match the passed regexp, but decide during block
|
|
21
|
+
processing that you do not want to treat it as a match, you can have the
|
|
22
|
+
block return nil or false. This is useful if you want to make sure you
|
|
23
|
+
are using valid data:
|
|
24
|
+
|
|
25
|
+
symbol_matcher(:date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
|
|
26
|
+
y = y.to_i
|
|
27
|
+
m = m.to_i
|
|
28
|
+
d = d.to_i
|
|
29
|
+
[Date.new(y, m, d)] if Date.valid_date?(y, m, d)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
When providing a block when using the symbol_matchers method, that
|
|
33
|
+
symbol may not work with the params_capturing plugin.
|
|
@@ -33,7 +33,7 @@ class Roda
|
|
|
33
33
|
# block return nil or false. This is useful if you want to make sure you
|
|
34
34
|
# are using valid data:
|
|
35
35
|
#
|
|
36
|
-
# class_matcher(Date, /(\
|
|
36
|
+
# class_matcher(Date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
|
|
37
37
|
# y = y.to_i
|
|
38
38
|
# m = m.to_i
|
|
39
39
|
# d = d.to_i
|
|
@@ -17,7 +17,7 @@ class Roda
|
|
|
17
17
|
# App.run "ro", OtherRodaApp
|
|
18
18
|
# App.run "si", SinatraApp
|
|
19
19
|
#
|
|
20
|
-
# Inside your route block, you can call r.multi_run to dispatch to all
|
|
20
|
+
# Inside your route block, you can call +r.multi_run+ to dispatch to all
|
|
21
21
|
# three rack applications based on the prefix:
|
|
22
22
|
#
|
|
23
23
|
# App.route do |r|
|
|
@@ -28,7 +28,7 @@ class Roda
|
|
|
28
28
|
# starting with +/ro+ to +OtherRodaApp+, and routes starting with +/si+ to
|
|
29
29
|
# SinatraApp.
|
|
30
30
|
#
|
|
31
|
-
# You can pass a block to +multi_run+ that will be called with the prefix,
|
|
31
|
+
# You can pass a block to +r.multi_run+ that will be called with the prefix,
|
|
32
32
|
# before dispatching to the rack app:
|
|
33
33
|
#
|
|
34
34
|
# App.route do |r|
|
|
@@ -39,12 +39,26 @@ class Roda
|
|
|
39
39
|
#
|
|
40
40
|
# This is useful for modifying the environment before passing it to the rack app.
|
|
41
41
|
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
42
|
+
# You can also call +Roda.run+ with a block:
|
|
43
|
+
#
|
|
44
|
+
# App.run("ra"){PlainRackApp}
|
|
45
|
+
# App.run("ro"){OtherRodaApp}
|
|
46
|
+
# App.run("si"){SinatraApp}
|
|
47
|
+
#
|
|
48
|
+
# When called with a block, Roda will call the block to get the app to dispatch to
|
|
49
|
+
# every time the block is called. The expected usage is with autoloaded classes,
|
|
50
|
+
# so that the related classes are not loaded until there is a request for the
|
|
51
|
+
# related route. This can sigficantly speedup startup or testing a subset of the
|
|
52
|
+
# application. When freezing an application, the blocks are called once to get the
|
|
53
|
+
# app to dispatch to, and that is cached, to ensure the any autoloads are completed
|
|
54
|
+
# before the application is frozen.
|
|
55
|
+
#
|
|
56
|
+
# The multi_run plugin is similar to the hash_branches and multi_route plugins, with
|
|
57
|
+
# the difference being the hash_branches and multi_route plugins keep all routing
|
|
58
|
+
# subtrees in the same Roda app/class, while multi_run dispatches to other rack apps.
|
|
59
|
+
# If you want to isolate your routing subtrees, multi_run is a better approach, but
|
|
60
|
+
# it does not let you set instance variables in the main Roda app and have those
|
|
61
|
+
# instance variables usable in the routing subtrees.
|
|
48
62
|
#
|
|
49
63
|
# To handle development environments that reload code, you can call the
|
|
50
64
|
# +run+ class method without an app to remove dispatching for the prefix.
|
|
@@ -52,12 +66,21 @@ class Roda
|
|
|
52
66
|
# Initialize the storage for the dispatched applications
|
|
53
67
|
def self.configure(app)
|
|
54
68
|
app.opts[:multi_run_apps] ||= {}
|
|
69
|
+
app.opts[:multi_run_app_blocks] ||= {}
|
|
55
70
|
end
|
|
56
71
|
|
|
57
72
|
module ClassMethods
|
|
73
|
+
# Convert app blocks into apps by calling them, in order to force autoloads
|
|
74
|
+
# and to speed up subsequent calls.
|
|
58
75
|
# Freeze the multi_run apps so that there can be no thread safety issues at runtime.
|
|
59
76
|
def freeze
|
|
60
|
-
opts[:
|
|
77
|
+
app_blocks = opts[:multi_run_app_blocks]
|
|
78
|
+
apps = opts[:multi_run_apps]
|
|
79
|
+
app_blocks.each do |prefix, block|
|
|
80
|
+
apps[prefix] = block.call
|
|
81
|
+
end
|
|
82
|
+
app_blocks.clear.freeze
|
|
83
|
+
apps.freeze
|
|
61
84
|
self::RodaRequest.refresh_multi_run_regexp!
|
|
62
85
|
super
|
|
63
86
|
end
|
|
@@ -69,12 +92,22 @@ class Roda
|
|
|
69
92
|
end
|
|
70
93
|
|
|
71
94
|
# Add a rack application to dispatch to for the given prefix when
|
|
72
|
-
# r.multi_run is called.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
95
|
+
# r.multi_run is called. If a block is given, it is called every time
|
|
96
|
+
# there is a request for the route to get the app to call. If neither
|
|
97
|
+
# a block or an app is provided, any stored route for the prefix is
|
|
98
|
+
# removed. It is an error to provide both an app and block in the same call.
|
|
99
|
+
def run(prefix, app=nil, &block)
|
|
100
|
+
prefix = prefix.to_s
|
|
101
|
+
if app
|
|
102
|
+
raise Roda::RodaError, "cannot provide both app and block to Roda.run" if block
|
|
103
|
+
opts[:multi_run_apps][prefix] = app
|
|
104
|
+
opts[:multi_run_app_blocks].delete(prefix)
|
|
105
|
+
elsif block
|
|
106
|
+
opts[:multi_run_apps].delete(prefix)
|
|
107
|
+
opts[:multi_run_app_blocks][prefix] = block
|
|
76
108
|
else
|
|
77
|
-
multi_run_apps.delete(prefix
|
|
109
|
+
opts[:multi_run_apps].delete(prefix)
|
|
110
|
+
opts[:multi_run_app_blocks].delete(prefix)
|
|
78
111
|
end
|
|
79
112
|
self::RodaRequest.refresh_multi_run_regexp!
|
|
80
113
|
end
|
|
@@ -84,7 +117,7 @@ class Roda
|
|
|
84
117
|
# Refresh the multi_run_regexp, using the stored route prefixes,
|
|
85
118
|
# preferring longer routes before shorter routes.
|
|
86
119
|
def refresh_multi_run_regexp!
|
|
87
|
-
@multi_run_regexp = /(#{Regexp.union(roda_class.multi_run_apps.keys.sort.reverse)})/
|
|
120
|
+
@multi_run_regexp = /(#{Regexp.union((roda_class.opts[:multi_run_apps].keys + roda_class.opts[:multi_run_app_blocks].keys).sort.reverse)})/
|
|
88
121
|
end
|
|
89
122
|
|
|
90
123
|
# Refresh the multi_run_regexp if it hasn't been loaded yet.
|
|
@@ -95,11 +128,12 @@ class Roda
|
|
|
95
128
|
|
|
96
129
|
module RequestMethods
|
|
97
130
|
# If one of the stored route prefixes match the current request,
|
|
98
|
-
# dispatch the request to the
|
|
131
|
+
# dispatch the request to the appropriate rack application.
|
|
99
132
|
def multi_run
|
|
100
133
|
on self.class.multi_run_regexp do |prefix|
|
|
101
134
|
yield prefix if defined?(yield)
|
|
102
|
-
|
|
135
|
+
opts = scope.opts
|
|
136
|
+
run(opts[:multi_run_apps][prefix] || opts[:multi_run_app_blocks][prefix].call)
|
|
103
137
|
end
|
|
104
138
|
end
|
|
105
139
|
end
|
|
@@ -37,6 +37,35 @@ class Roda
|
|
|
37
37
|
#
|
|
38
38
|
# If using this plugin with the params_capturing plugin, this plugin should
|
|
39
39
|
# be loaded first.
|
|
40
|
+
#
|
|
41
|
+
# You can provide a block when calling +symbol_matcher+, and it will be called
|
|
42
|
+
# for all matches to allow for type conversion. The block must return an
|
|
43
|
+
# array:
|
|
44
|
+
#
|
|
45
|
+
# symbol_matcher(:date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
|
|
46
|
+
# [Date.new(y.to_i, m.to_i, d.to_i)]
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# route do |r|
|
|
50
|
+
# r.on :date do |date|
|
|
51
|
+
# # date is an instance of Date
|
|
52
|
+
# end
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# If you have a segment match the passed regexp, but decide during block
|
|
56
|
+
# processing that you do not want to treat it as a match, you can have the
|
|
57
|
+
# block return nil or false. This is useful if you want to make sure you
|
|
58
|
+
# are using valid data:
|
|
59
|
+
#
|
|
60
|
+
# symbol_matcher(:date, /(\d\d\d\d)-(\d\d)-(\d\d)/) do |y, m, d|
|
|
61
|
+
# y = y.to_i
|
|
62
|
+
# m = m.to_i
|
|
63
|
+
# d = d.to_i
|
|
64
|
+
# [Date.new(y, m, d)] if Date.valid_date?(y, m, d)
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# However, if providing a block to the symbol_matchers plugin, the symbol may
|
|
68
|
+
# not work with the params_capturing plugin.
|
|
40
69
|
module SymbolMatchers
|
|
41
70
|
def self.load_dependencies(app)
|
|
42
71
|
app.plugin :_symbol_regexp_matchers
|
|
@@ -50,9 +79,10 @@ class Roda
|
|
|
50
79
|
|
|
51
80
|
module ClassMethods
|
|
52
81
|
# Set the regexp to use for the given symbol, instead of the default.
|
|
53
|
-
def symbol_matcher(s, re)
|
|
82
|
+
def symbol_matcher(s, re, &block)
|
|
54
83
|
meth = :"match_symbol_#{s}"
|
|
55
|
-
|
|
84
|
+
array = [re, block].freeze
|
|
85
|
+
self::RodaRequest.send(:define_method, meth){array}
|
|
56
86
|
self::RodaRequest.send(:private, meth)
|
|
57
87
|
end
|
|
58
88
|
end
|
|
@@ -67,8 +97,8 @@ class Roda
|
|
|
67
97
|
meth = :"match_symbol_#{s}"
|
|
68
98
|
if respond_to?(meth, true)
|
|
69
99
|
# Allow calling private match methods
|
|
70
|
-
re = send(meth)
|
|
71
|
-
consume(self.class.cached_matcher(re){re})
|
|
100
|
+
re, block = send(meth)
|
|
101
|
+
consume(self.class.cached_matcher(re){re}, &block)
|
|
72
102
|
else
|
|
73
103
|
super
|
|
74
104
|
end
|
|
@@ -80,7 +110,8 @@ class Roda
|
|
|
80
110
|
meth = :"match_symbol_#{s}"
|
|
81
111
|
if respond_to?(meth, true)
|
|
82
112
|
# Allow calling private match methods
|
|
83
|
-
send(meth)
|
|
113
|
+
re, = send(meth)
|
|
114
|
+
re
|
|
84
115
|
else
|
|
85
116
|
super
|
|
86
117
|
end
|
data/lib/roda/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: roda
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.69.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremy Evans
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-06-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -240,6 +240,8 @@ extra_rdoc_files:
|
|
|
240
240
|
- doc/release_notes/3.65.0.txt
|
|
241
241
|
- doc/release_notes/3.66.0.txt
|
|
242
242
|
- doc/release_notes/3.67.0.txt
|
|
243
|
+
- doc/release_notes/3.68.0.txt
|
|
244
|
+
- doc/release_notes/3.69.0.txt
|
|
243
245
|
- doc/release_notes/3.7.0.txt
|
|
244
246
|
- doc/release_notes/3.8.0.txt
|
|
245
247
|
- doc/release_notes/3.9.0.txt
|
|
@@ -314,6 +316,8 @@ files:
|
|
|
314
316
|
- doc/release_notes/3.65.0.txt
|
|
315
317
|
- doc/release_notes/3.66.0.txt
|
|
316
318
|
- doc/release_notes/3.67.0.txt
|
|
319
|
+
- doc/release_notes/3.68.0.txt
|
|
320
|
+
- doc/release_notes/3.69.0.txt
|
|
317
321
|
- doc/release_notes/3.7.0.txt
|
|
318
322
|
- doc/release_notes/3.8.0.txt
|
|
319
323
|
- doc/release_notes/3.9.0.txt
|