roda 3.49.0 → 3.53.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +34 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -1
- data/doc/release_notes/3.50.0.txt +21 -0
- data/doc/release_notes/3.51.0.txt +20 -0
- data/doc/release_notes/3.52.0.txt +20 -0
- data/doc/release_notes/3.53.0.txt +14 -0
- data/lib/roda/plugins/additional_view_directories.rb +68 -0
- data/lib/roda/plugins/assets.rb +10 -2
- data/lib/roda/plugins/capture_erb.rb +41 -0
- data/lib/roda/plugins/content_for.rb +7 -13
- data/lib/roda/plugins/error_handler.rb +1 -0
- data/lib/roda/plugins/hash_routes.rb +16 -4
- data/lib/roda/plugins/indifferent_params.rb +17 -5
- data/lib/roda/plugins/inject_erb.rb +33 -0
- data/lib/roda/plugins/multi_route.rb +1 -0
- data/lib/roda/plugins/multi_run.rb +9 -2
- data/lib/roda/plugins/named_routes.rb +10 -2
- data/lib/roda/plugins/path.rb +11 -2
- data/lib/roda/plugins/render.rb +81 -3
- data/lib/roda/plugins/status_303.rb +1 -2
- data/lib/roda/plugins/typecast_params.rb +39 -1
- data/lib/roda/version.rb +1 -1
- metadata +15 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90bdf6d366ffc4bff40aa51721176291fadb80f56d7904965fe46a1385fe4172
|
4
|
+
data.tar.gz: ab1bea5320b4049e918ebb23d1b081c26d5401000f11b02c5f85a1e1b30899c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13bc3beb138174dc8cadfc309458bd1821cbe8b6f80f1cb704752979bf085710181d5fd9df71a3cc1fba2be3b258721f36c8758e202961f9389f23b7555ee78b
|
7
|
+
data.tar.gz: 7129008315908bf7ebd6c0115cd8eb531a6357617a5f9ce3a0ffae3703a5cd68793af0d43ac4703752e280a5cc6090234b60640fe25384c4fa8aabe8e04b94af
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
= 3.53.0 (2022-02-14)
|
2
|
+
|
3
|
+
* Make indifferent_params plugin support rack main branch (jeremyevans)
|
4
|
+
|
5
|
+
* Add additional_view_directories plugin, for checking multiple view directories for templates (jeremyevans) (#229)
|
6
|
+
|
7
|
+
= 3.52.0 (2022-01-14)
|
8
|
+
|
9
|
+
* Fix return value of Roda.freeze when multi_route plugin is used (jeremyevans) (#240)
|
10
|
+
|
11
|
+
* Use faster OpenSSL::Digest instead of Digest for assets plugin SRI support (jeremyevans)
|
12
|
+
|
13
|
+
* Drop development dependency on haml (jeremyevans)
|
14
|
+
|
15
|
+
* Make the path method in the path plugin handle blocks that accept keyword arguments in Ruby 3+ (adam12) (#227)
|
16
|
+
|
17
|
+
* Support typecast_params :date_parse_input_handler plugin option for handling input to date parsing methods (jeremyevans)
|
18
|
+
|
19
|
+
= 3.51.0 (2021-12-15)
|
20
|
+
|
21
|
+
* Avoid method redefinition warning in error_handler plugin in verbose warning mode (jeremyevans)
|
22
|
+
|
23
|
+
* Allow run in multi_run plugin to be called without an app to remove existing handler (jeremyevans)
|
24
|
+
|
25
|
+
* Allow route in named_routes plugin to be called without a block to remove existing handler (jeremyevans)
|
26
|
+
|
27
|
+
= 3.50.0 (2021-11-12)
|
28
|
+
|
29
|
+
* Add capture_erb plugin for capturing ERB template blocks, instead of injecting them into the template output (jeremyevans)
|
30
|
+
|
31
|
+
* Add inject_erb plugin for injecting content directly into ERB template output (jeremyevans)
|
32
|
+
|
33
|
+
* Allow hash_branch and hash_path in hash_routes plugin to be called without a block to remove existing handler (jeremyevans)
|
34
|
+
|
1
35
|
= 3.49.0 (2021-10-13)
|
2
36
|
|
3
37
|
* Switch block_given? to defined?(yield) (jeremyevans)
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -12,7 +12,8 @@ maintainable web applications in ruby.
|
|
12
12
|
Website :: http://roda.jeremyevans.net
|
13
13
|
Source :: http://github.com/jeremyevans/roda
|
14
14
|
Bugs :: http://github.com/jeremyevans/roda/issues
|
15
|
-
|
15
|
+
Discussion Forum (GitHub Discussions) :: https://github.com/jeremyevans/roda/discussions
|
16
|
+
Alternate Discussion Forum (Google Group) :: http://groups.google.com/group/ruby-roda
|
16
17
|
|
17
18
|
== Goals
|
18
19
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An inject_erb plugin has been added, adding an inject_erb method
|
4
|
+
that allows for injecting content directly into the template output
|
5
|
+
for the template currently being rendered. This allows you to more
|
6
|
+
easily wrap blocks in templates, by calling methods that accept
|
7
|
+
template blocks and injecting content before and after the block.
|
8
|
+
|
9
|
+
* A capture_erb plugin has been added, adding a capture_erb method
|
10
|
+
for capturing a template block in an erb template and returning
|
11
|
+
the content appended during the block as a string, instead of
|
12
|
+
having the content of the template block be included directly into
|
13
|
+
the template output. This can be combined with the inject_erb
|
14
|
+
plugin to inject modified versions of captured blocks into template
|
15
|
+
output.
|
16
|
+
|
17
|
+
* The hash_routes plugin now allows calling hash_branch and hash_path
|
18
|
+
without a block in order to remove the existing route handler. This
|
19
|
+
is designed to be used with code reloading libraries, so that if a
|
20
|
+
route file is deleted, the related hash branches/paths are also
|
21
|
+
removed, without having to reload all route files.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* The named_routes plugin now allows calling route without a block
|
4
|
+
to remove the existing route handler. The multi_run plugin
|
5
|
+
now allows calling run without an app to remove an existing handler.
|
6
|
+
These changes are designed to better support code reloading
|
7
|
+
libraries, so that if the related file is deleted, the related
|
8
|
+
handlers are also removed, without having to reload the entire
|
9
|
+
application.
|
10
|
+
|
11
|
+
= Other Improvements
|
12
|
+
|
13
|
+
* The error_handler plugin now avoids a method redefinition warning
|
14
|
+
in verbose warning mode.
|
15
|
+
|
16
|
+
= Other
|
17
|
+
|
18
|
+
* Roda's primary discussion forum is now GitHub Discussions. The
|
19
|
+
ruby-roda Google Group is still available for users who would
|
20
|
+
prefer to use that instead.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* The typecast_params plugin now supports a :date_parse_input_handler
|
4
|
+
option that will be called with all input that will be passed to
|
5
|
+
the date parsing methods. You can use this option to automatically
|
6
|
+
truncate input, if that is perferable to raising an error (which is
|
7
|
+
how recent versions of Ruby handle too-long input).
|
8
|
+
|
9
|
+
= Other Improvements
|
10
|
+
|
11
|
+
* The path helper methods added by the path plugin now support
|
12
|
+
blocks that use keyword arguments on Ruby 3+.
|
13
|
+
|
14
|
+
* The assets plugin now uses OpenSSL::Digest instead of Digest (if
|
15
|
+
available) for calculating SRI digests. This is faster on Ruby 3+,
|
16
|
+
where Digest no longer uses the faster OpenSSL::Digest automatically
|
17
|
+
if available.
|
18
|
+
|
19
|
+
* Roda.freeze now returns self when the multi_route plugin is used.
|
20
|
+
This was broken (not returning self) starting in 3.48.0.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An additional_view_directories plugin has been added, which allows
|
4
|
+
you to specify additional directories to look in for templates.
|
5
|
+
If the template path does not exist when using the default view
|
6
|
+
directory, then each additional view directory will be checked,
|
7
|
+
returning the first path that exists:
|
8
|
+
|
9
|
+
plugin :additional_view_directories, ['admin_views', 'public_views']
|
10
|
+
|
11
|
+
= Other Improvements
|
12
|
+
|
13
|
+
* The indifferent_params plugin now avoids a deprecation warning when
|
14
|
+
using the rack main branch, which will become Rack 3.
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The additional_view_directories plugin allows for specifying additional view
|
7
|
+
# directories to look in for templates. When rendering a template, it will
|
8
|
+
# first try the :views directory specified in the render plugin. If the template
|
9
|
+
# file to be rendered does not exist in that directory, it will try each additional
|
10
|
+
# view directory specified in this plugin, in order, using the path to the first
|
11
|
+
# template file that exists in the file system. If no such path is found, it
|
12
|
+
# uses the default path specified by the render plugin.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# plugin :render, :views=>'dir'
|
17
|
+
# plugin :additional_view_directories, ['dir1', 'dir2', 'dir3']
|
18
|
+
#
|
19
|
+
# route do |r|
|
20
|
+
# # Will check the following in order, using path for first
|
21
|
+
# # template file that exists:
|
22
|
+
# # * dir/t.erb
|
23
|
+
# # * dir1/t.erb
|
24
|
+
# # * dir2/t.erb
|
25
|
+
# # * dir3/t.erb
|
26
|
+
# render :t
|
27
|
+
# end
|
28
|
+
module AdditionalViewDirectories
|
29
|
+
# Depend on the render plugin, since this plugin only makes
|
30
|
+
# sense when the render plugin is used.
|
31
|
+
def self.load_dependencies(app, view_dirs)
|
32
|
+
app.plugin :render
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set the additional view directories to look in. Each additional view directory
|
36
|
+
# is also added as an allowed path.
|
37
|
+
def self.configure(app, view_dirs)
|
38
|
+
view_dirs = app.opts[:additional_view_directories] = view_dirs.map{|f| app.expand_path(f, nil)}.freeze
|
39
|
+
opts = app.opts[:render]
|
40
|
+
app.opts[:render] = opts.merge(:allowed_paths=>(opts[:allowed_paths] + view_dirs).uniq.freeze)
|
41
|
+
opts.freeze
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
private
|
46
|
+
|
47
|
+
# If the template path does not exist, try looking for the template
|
48
|
+
# in each of the additional view directories, in order, returning
|
49
|
+
# the first path that exists. If no additional directory includes
|
50
|
+
# the template, return the original path.
|
51
|
+
def template_path(opts)
|
52
|
+
orig_path = super
|
53
|
+
|
54
|
+
unless File.file?(orig_path)
|
55
|
+
self.opts[:additional_view_directories].each do |view_dir|
|
56
|
+
path = super(opts.merge(:views=>view_dir))
|
57
|
+
return path if File.file?(path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
orig_path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
register_plugin(:additional_view_directories, AdditionalViewDirectories)
|
67
|
+
end
|
68
|
+
end
|
data/lib/roda/plugins/assets.rb
CHANGED
@@ -641,9 +641,17 @@ class Roda
|
|
641
641
|
# a different digest type or to return a static string if you don't
|
642
642
|
# want to use a unique value.
|
643
643
|
def asset_digest(content)
|
644
|
-
require 'digest/sha2'
|
645
644
|
algo = assets_opts[:sri] || :sha256
|
646
|
-
|
645
|
+
digest = begin
|
646
|
+
require 'openssl'
|
647
|
+
::OpenSSL::Digest
|
648
|
+
# :nocov:
|
649
|
+
rescue LoadError
|
650
|
+
require 'digest/sha2'
|
651
|
+
::Digest
|
652
|
+
# :nocov:
|
653
|
+
end
|
654
|
+
digest.const_get(algo.to_s.upcase).hexdigest(content)
|
647
655
|
end
|
648
656
|
end
|
649
657
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The capture_erb plugin allows you to capture the content of a block
|
7
|
+
# in an ERB template, and return it as a value, instead of
|
8
|
+
# injecting the template block into the template output.
|
9
|
+
#
|
10
|
+
# <% value = capture_erb do %>
|
11
|
+
# Some content here.
|
12
|
+
# <% end %>
|
13
|
+
#
|
14
|
+
# +capture_erb+ can be used inside other methods that are called
|
15
|
+
# inside templates. It can be combined with the inject_erb plugin
|
16
|
+
# to wrap template blocks with arbitrary output and then inject the
|
17
|
+
# wrapped output into the template.
|
18
|
+
module CaptureERB
|
19
|
+
def self.load_dependencies(app)
|
20
|
+
app.plugin :render
|
21
|
+
end
|
22
|
+
|
23
|
+
module InstanceMethods
|
24
|
+
# Temporarily replace the ERB output buffer
|
25
|
+
# with an empty string, and then yield to the block.
|
26
|
+
# Return the value of the block, converted to a string.
|
27
|
+
# Restore the previous ERB output buffer before returning.
|
28
|
+
def capture_erb
|
29
|
+
outvar = render_opts[:template_opts][:outvar]
|
30
|
+
buf_was = instance_variable_get(outvar)
|
31
|
+
instance_variable_set(outvar, String.new)
|
32
|
+
yield.to_s
|
33
|
+
ensure
|
34
|
+
instance_variable_set(outvar, buf_was) if outvar && buf_was
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
register_plugin(:capture_erb, CaptureERB)
|
40
|
+
end
|
41
|
+
end
|
@@ -55,10 +55,10 @@ class Roda
|
|
55
55
|
#
|
56
56
|
# plugin :content_for, append: false
|
57
57
|
module ContentFor
|
58
|
-
# Depend on the
|
59
|
-
#
|
58
|
+
# Depend on the capture_erb plugin, since it uses capture_erb
|
59
|
+
# to capture the content.
|
60
60
|
def self.load_dependencies(app, _opts = OPTS)
|
61
|
-
app.plugin :
|
61
|
+
app.plugin :capture_erb
|
62
62
|
end
|
63
63
|
|
64
64
|
# Configure whether to append or overwrite if content_for
|
@@ -72,18 +72,12 @@ class Roda
|
|
72
72
|
# under the given key. If called without a block, retrieve
|
73
73
|
# stored content with the given key, or return nil if there
|
74
74
|
# is no content stored with that key.
|
75
|
-
def content_for(key, value=nil)
|
75
|
+
def content_for(key, value=nil, &block)
|
76
76
|
append = opts[:append_content_for]
|
77
77
|
|
78
|
-
if
|
79
|
-
if
|
80
|
-
|
81
|
-
buf_was = instance_variable_get(outvar)
|
82
|
-
|
83
|
-
# Use temporary output buffer for ERB-based rendering systems
|
84
|
-
instance_variable_set(outvar, String.new)
|
85
|
-
value = yield.to_s
|
86
|
-
instance_variable_set(outvar, buf_was)
|
78
|
+
if block || value
|
79
|
+
if block
|
80
|
+
value = capture_erb(&block)
|
87
81
|
end
|
88
82
|
|
89
83
|
@_content_for ||= {}
|
@@ -394,20 +394,32 @@ class Roda
|
|
394
394
|
dsl
|
395
395
|
end
|
396
396
|
|
397
|
-
# Add branch handler for the given namespace and segment.
|
397
|
+
# Add branch handler for the given namespace and segment. If called without
|
398
|
+
# a block, removes the existing branch handler if it exists.
|
398
399
|
def hash_branch(namespace='', segment, &block)
|
399
400
|
segment = "/#{segment}"
|
400
401
|
routes = opts[:hash_branches][namespace] ||= {}
|
401
|
-
|
402
|
+
if block
|
403
|
+
routes[segment] = define_roda_method(routes[segment] || "hash_branch_#{namespace}_#{segment}", 1, &convert_route_block(block))
|
404
|
+
elsif meth = routes[segment]
|
405
|
+
routes.delete(segment)
|
406
|
+
remove_method(meth)
|
407
|
+
end
|
402
408
|
end
|
403
409
|
|
404
410
|
# Add path handler for the given namespace and path. When the
|
405
411
|
# r.hash_paths method is called, checks the matching namespace
|
406
412
|
# for the full remaining path, and dispatch to that block if
|
407
|
-
# there is one.
|
413
|
+
# there is one. If called without a block, removes the existing
|
414
|
+
# path handler if it exists.
|
408
415
|
def hash_path(namespace='', path, &block)
|
409
416
|
routes = opts[:hash_paths][namespace] ||= {}
|
410
|
-
|
417
|
+
if block
|
418
|
+
routes[path] = define_roda_method(routes[path] || "hash_path_#{namespace}_#{path}", 1, &convert_route_block(block))
|
419
|
+
elsif meth = routes[path]
|
420
|
+
routes.delete(path)
|
421
|
+
remove_method(meth)
|
422
|
+
end
|
411
423
|
end
|
412
424
|
end
|
413
425
|
|
@@ -52,17 +52,29 @@ class Roda
|
|
52
52
|
end
|
53
53
|
|
54
54
|
class Params < Rack::QueryParser::Params
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
# :nocov:
|
56
|
+
if Rack.release >= '2.3'
|
57
|
+
def initialize
|
58
|
+
@size = 0
|
59
|
+
@params = Hash.new(&INDIFFERENT_PROC)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
# :nocov:
|
63
|
+
def initialize(limit = Rack::Utils.key_space_limit)
|
64
|
+
@limit = limit
|
65
|
+
@size = 0
|
66
|
+
@params = Hash.new(&INDIFFERENT_PROC)
|
67
|
+
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
62
71
|
end
|
63
72
|
|
64
73
|
module RequestMethods
|
65
|
-
|
74
|
+
# :nocov:
|
75
|
+
query_parser = Rack.release >= '2.3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32)
|
76
|
+
# :nocov:
|
77
|
+
QUERY_PARSER = Rack::Utils.default_query_parser = query_parser
|
66
78
|
|
67
79
|
private
|
68
80
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The inject_erb plugin allows you to inject content directly
|
7
|
+
# into the template output:
|
8
|
+
#
|
9
|
+
# <% inject_erb("Some HTML Here") %>
|
10
|
+
#
|
11
|
+
# This will inject <tt>Some HTML Here</tt> into the template output,
|
12
|
+
# even though the tag being used is <tt><%</tt> and not <tt><%=</tt>.
|
13
|
+
#
|
14
|
+
# This method can be used inside methods, such as to wrap calls to
|
15
|
+
# methods that accept template blocks, to inject code before and after
|
16
|
+
# the template blocks.
|
17
|
+
module InjectERB
|
18
|
+
def self.load_dependencies(app)
|
19
|
+
app.plugin :render
|
20
|
+
end
|
21
|
+
|
22
|
+
module InstanceMethods
|
23
|
+
# Inject into the template output for the template currently being
|
24
|
+
# rendered.
|
25
|
+
def inject_erb(value)
|
26
|
+
instance_variable_get(render_opts[:template_opts][:outvar]) << value.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
register_plugin(:inject_erb, InjectERB)
|
32
|
+
end
|
33
|
+
end
|
@@ -45,6 +45,9 @@ class Roda
|
|
45
45
|
# subtrees, multi_run is a better approach, but it does not let you set instance
|
46
46
|
# variables in the main Roda app and have those instance variables usable in
|
47
47
|
# the routing subtrees.
|
48
|
+
#
|
49
|
+
# To handle development environments that reload code, you can call the
|
50
|
+
# +run+ class method without an app to remove dispatching for the prefix.
|
48
51
|
module MultiRun
|
49
52
|
# Initialize the storage for the dispatched applications
|
50
53
|
def self.configure(app)
|
@@ -67,8 +70,12 @@ class Roda
|
|
67
70
|
|
68
71
|
# Add a rack application to dispatch to for the given prefix when
|
69
72
|
# r.multi_run is called.
|
70
|
-
def run(prefix, app)
|
71
|
-
|
73
|
+
def run(prefix, app=nil)
|
74
|
+
if app
|
75
|
+
multi_run_apps[prefix.to_s] = app
|
76
|
+
else
|
77
|
+
multi_run_apps.delete(prefix.to_s)
|
78
|
+
end
|
72
79
|
self::RodaRequest.refresh_multi_run_regexp!
|
73
80
|
end
|
74
81
|
end
|
@@ -38,6 +38,9 @@ class Roda
|
|
38
38
|
# Note that in multi-threaded code, you should not attempt to add a
|
39
39
|
# named route after accepting requests.
|
40
40
|
#
|
41
|
+
# To handle development environments that reload code, you can call the
|
42
|
+
# +route+ class method without a block to remove an existing named route.
|
43
|
+
#
|
41
44
|
# == Routing Files
|
42
45
|
#
|
43
46
|
# The convention when using the named_routes plugin is to have a single
|
@@ -124,7 +127,7 @@ class Roda
|
|
124
127
|
# The names for the currently stored named routes
|
125
128
|
def named_routes(namespace=nil)
|
126
129
|
unless routes = opts[:namespaced_routes][namespace]
|
127
|
-
raise RodaError, "unsupported
|
130
|
+
raise RodaError, "unsupported named_routes namespace used: #{namespace.inspect}"
|
128
131
|
end
|
129
132
|
routes.keys
|
130
133
|
end
|
@@ -140,7 +143,12 @@ class Roda
|
|
140
143
|
def route(name=nil, namespace=nil, &block)
|
141
144
|
if name
|
142
145
|
routes = opts[:namespaced_routes][namespace] ||= {}
|
143
|
-
|
146
|
+
if block
|
147
|
+
routes[name] = define_roda_method(routes[name] || "named_routes_#{namespace}_#{name}", 1, &convert_route_block(block))
|
148
|
+
elsif meth = routes[name]
|
149
|
+
routes.delete(name)
|
150
|
+
remove_method(meth)
|
151
|
+
end
|
144
152
|
else
|
145
153
|
super(&block)
|
146
154
|
end
|
data/lib/roda/plugins/path.rb
CHANGED
@@ -41,12 +41,12 @@ class Roda
|
|
41
41
|
# end
|
42
42
|
#
|
43
43
|
# r.post 'baz' do
|
44
|
-
#
|
44
|
+
# baz = Baz[1]
|
45
45
|
# r.redirect path(baz, 'c', 'd') # /baz/1/c/d
|
46
46
|
# end
|
47
47
|
#
|
48
48
|
# r.post 'quux' do
|
49
|
-
#
|
49
|
+
# quux = Quux[1]
|
50
50
|
# r.redirect url(quux, '/bar') # http://example.com/quux/1/bar
|
51
51
|
# end
|
52
52
|
# end
|
@@ -148,11 +148,17 @@ class Roda
|
|
148
148
|
# Allow calling private _method to get path
|
149
149
|
relative_path(request.script_name.to_s + send(_meth, *a, &blk))
|
150
150
|
end
|
151
|
+
# :nocov:
|
152
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
|
153
|
+
# :nocov:
|
151
154
|
elsif add_script_name
|
152
155
|
define_method(meth) do |*a, &blk|
|
153
156
|
# Allow calling private _method to get path
|
154
157
|
request.script_name.to_s + send(_meth, *a, &blk)
|
155
158
|
end
|
159
|
+
# :nocov:
|
160
|
+
ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
|
161
|
+
# :nocov:
|
156
162
|
else
|
157
163
|
define_method(meth, &block)
|
158
164
|
end
|
@@ -171,6 +177,9 @@ class Roda
|
|
171
177
|
end
|
172
178
|
|
173
179
|
define_method(url_meth, &url_block)
|
180
|
+
# :nocov:
|
181
|
+
ruby2_keywords(url_meth) if respond_to?(:ruby2_keywords, true)
|
182
|
+
# :nocov:
|
174
183
|
end
|
175
184
|
|
176
185
|
nil
|
data/lib/roda/plugins/render.rb
CHANGED
@@ -47,7 +47,7 @@ class Roda
|
|
47
47
|
# The following plugin options are supported:
|
48
48
|
#
|
49
49
|
# :allowed_paths :: Set the template paths to allow. Attempts to render paths outside
|
50
|
-
# of
|
50
|
+
# of these paths will raise an error. Defaults to the +:views+ directory.
|
51
51
|
# :cache :: nil/false to explicitly disable premanent template caching. By default, permanent
|
52
52
|
# template caching is disabled by default if RACK_ENV is development. When permanent
|
53
53
|
# template caching is disabled, for templates with paths in the file system, the
|
@@ -59,9 +59,9 @@ class Roda
|
|
59
59
|
# templates, defaults to 'erb'.
|
60
60
|
# :escape :: Use Erubi as the ERB template engine, and enable escaping by default,
|
61
61
|
# which makes <tt><%= %></tt> escape output and <tt><%== %></tt> not escape output.
|
62
|
-
# If given, sets the <tt
|
62
|
+
# If given, sets the <tt>escape: true</tt> option for all template engines, which
|
63
63
|
# can break some non-ERB template engines. You can use a string or array of strings
|
64
|
-
# as the value for this option to only set the <tt
|
64
|
+
# as the value for this option to only set the <tt>escape: true</tt> option for those
|
65
65
|
# specific template engines.
|
66
66
|
# :layout :: The base name of the layout file, defaults to 'layout'. This can be provided as a hash
|
67
67
|
# with the :template or :inline options.
|
@@ -130,6 +130,84 @@ class Roda
|
|
130
130
|
# only argument, you can speed things up by specifying a +:cache_key+ option in
|
131
131
|
# the hash, making sure the +:cache_key+ is unique to the template you are
|
132
132
|
# rendering.
|
133
|
+
#
|
134
|
+
# = Accepting Template Blocks in Methods
|
135
|
+
#
|
136
|
+
# If you are used to Rails, you may be surprised that this type of template code
|
137
|
+
# doesn't work in Roda:
|
138
|
+
#
|
139
|
+
# <%= some_method do %>
|
140
|
+
# Some HTML
|
141
|
+
# <% end %>
|
142
|
+
#
|
143
|
+
# The reason this doesn't work is that this is not valid ERB syntax, it is Rails syntax,
|
144
|
+
# and requires attempting to parse the <tt>some_method do</tt> Ruby code with a regular
|
145
|
+
# expression. Since Roda uses ERB syntax, it does not support this.
|
146
|
+
#
|
147
|
+
# In general, these methods are used to wrap the content of the block and
|
148
|
+
# inject the content into the output. To get similar behavior with Roda, you have
|
149
|
+
# a few different options you can use.
|
150
|
+
#
|
151
|
+
# == Directly Inject Template Output
|
152
|
+
#
|
153
|
+
# You can switch from a <tt><%=</tt> tag to using a <tt><%</tt> tag:
|
154
|
+
#
|
155
|
+
# <% some_method do %>
|
156
|
+
# Some HTML
|
157
|
+
# <% end %>
|
158
|
+
#
|
159
|
+
# While this would output <tt>Some HTML</tt> into the template, it would not be able
|
160
|
+
# to inject content before or after the block. However, you can use the inject_erb_plugin
|
161
|
+
# to handle the injection:
|
162
|
+
#
|
163
|
+
# def some_method
|
164
|
+
# inject_erb "content before block"
|
165
|
+
# yield
|
166
|
+
# inject_erb "content after block"
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# If you need to modify the captured block before injecting it, you can use the
|
170
|
+
# capture_erb plugin to capture content from the template block, and modify that content,
|
171
|
+
# then use inject_erb to inject it into the template output:
|
172
|
+
#
|
173
|
+
# def some_method(&block)
|
174
|
+
# inject_erb "content before block"
|
175
|
+
# inject_erb capture_erb(&block).upcase
|
176
|
+
# inject_erb "content after block"
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# This is the recommended approach for handling this type of method, if you want to keep
|
180
|
+
# the template block in the same template.
|
181
|
+
#
|
182
|
+
# == Separate Block Output Into Separate Template
|
183
|
+
#
|
184
|
+
# By moving the <tt>Some HTML</tt> into a separate template, you can render that
|
185
|
+
# template inside the block:
|
186
|
+
#
|
187
|
+
# <%= some_method{render('template_name')} %>
|
188
|
+
#
|
189
|
+
# It's also possible to use an inline template:
|
190
|
+
#
|
191
|
+
# <%= some_method do render(:inline=><<-END)
|
192
|
+
# Some HTML
|
193
|
+
# END
|
194
|
+
# end %>
|
195
|
+
#
|
196
|
+
# This approach is useful if it makes sense to separate the template block into its
|
197
|
+
# own template. You lose the ability to use local variable from outside the
|
198
|
+
# template block inside the template block with this approach.
|
199
|
+
#
|
200
|
+
# == Separate Header and Footer
|
201
|
+
#
|
202
|
+
# You can define two separate methods, one that outputs the content before the block,
|
203
|
+
# and one that outputs the content after the block, and use those instead of a single
|
204
|
+
# call:
|
205
|
+
#
|
206
|
+
# <%= some_method_before %>
|
207
|
+
# Some HTML
|
208
|
+
# <%= some_method_after %>
|
209
|
+
#
|
210
|
+
# This is the simplest option to setup, but it is fairly tedious to use.
|
133
211
|
module Render
|
134
212
|
# Support for using compiled methods directly requires Ruby 2.3 for the
|
135
213
|
# method binding to work, and Tilt 1.2 for Tilt::Template#compiled_method.
|
@@ -6,8 +6,7 @@ class Roda
|
|
6
6
|
# The status_303 plugin sets the default redirect status to be 303
|
7
7
|
# rather than 302 when the request is not a GET and the
|
8
8
|
# redirection occurs on an HTTP 1.1 connection as per RFC 7231.
|
9
|
-
#
|
10
|
-
# practice.
|
9
|
+
# There are some frontend frameworks that require this behavior.
|
11
10
|
#
|
12
11
|
# Example:
|
13
12
|
#
|
@@ -265,6 +265,23 @@ class Roda
|
|
265
265
|
# If you would like to skip this check and allow null bytes in param string values,
|
266
266
|
# you can do by passing the <tt>:allow_null_bytes</tt> option when loading the plugin.
|
267
267
|
#
|
268
|
+
# You can use the :date_parse_input_handler option to specify custom handling of date
|
269
|
+
# parsing input. Modern versions of Ruby and the date gem internally raise if the input to
|
270
|
+
# date parsing methods is too large to prevent denial of service. If you are using an
|
271
|
+
# older version of Ruby, you can use this option to enforce the same check:
|
272
|
+
#
|
273
|
+
# plugin :typecast_params, date_parse_input_handler: proc {|string|
|
274
|
+
# raise ArgumentError, "too big" if string.bytesize > 128
|
275
|
+
# string
|
276
|
+
# }
|
277
|
+
#
|
278
|
+
# You can also use this option to modify the input, such as truncating it to the first
|
279
|
+
# 128 bytes:
|
280
|
+
#
|
281
|
+
# plugin :typecast_params, date_parse_input_handler: proc {|string|
|
282
|
+
# string.b[0, 128]
|
283
|
+
# }
|
284
|
+
#
|
268
285
|
# By design, typecast_params only deals with string keys, it is not possible to use
|
269
286
|
# symbol keys as arguments to the conversion methods and have them converted.
|
270
287
|
module TypecastParams
|
@@ -384,6 +401,14 @@ class Roda
|
|
384
401
|
end
|
385
402
|
end
|
386
403
|
|
404
|
+
module DateParseInputHandler
|
405
|
+
# Pass input string to date parsing through handle_date_parse_input.
|
406
|
+
def _string_parse!(klass, v)
|
407
|
+
v = handle_date_parse_input(v)
|
408
|
+
super
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
387
412
|
# Class handling conversion of submitted parameters to desired types.
|
388
413
|
class Params
|
389
414
|
# Handle conversions for the given type using the given block.
|
@@ -999,11 +1024,16 @@ class Roda
|
|
999
1024
|
when ''
|
1000
1025
|
nil
|
1001
1026
|
when String
|
1002
|
-
klass
|
1027
|
+
_string_parse!(klass, v)
|
1003
1028
|
else
|
1004
1029
|
raise Error, "unexpected value received: #{v.inspect}"
|
1005
1030
|
end
|
1006
1031
|
end
|
1032
|
+
|
1033
|
+
# Handle parsing for string values passed to parse!.
|
1034
|
+
def _string_parse!(klass, v)
|
1035
|
+
klass.parse(v)
|
1036
|
+
end
|
1007
1037
|
end
|
1008
1038
|
|
1009
1039
|
# Set application-specific Params subclass unless one has been set,
|
@@ -1019,6 +1049,14 @@ class Roda
|
|
1019
1049
|
if opts[:allow_null_bytes]
|
1020
1050
|
app::TypecastParams.send(:include, AllowNullByte)
|
1021
1051
|
end
|
1052
|
+
if opts[:date_parse_input_handler]
|
1053
|
+
app::TypecastParams.class_eval do
|
1054
|
+
include DateParseInputHandler
|
1055
|
+
define_method(:handle_date_parse_input, &opts[:date_parse_input_handler])
|
1056
|
+
private :handle_date_parse_input
|
1057
|
+
alias handle_date_parse_input handle_date_parse_input
|
1058
|
+
end
|
1059
|
+
end
|
1022
1060
|
end
|
1023
1061
|
|
1024
1062
|
module ClassMethods
|
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.53.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:
|
11
|
+
date: 2022-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -94,20 +94,6 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: haml
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: rack_csrf
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -221,6 +207,10 @@ extra_rdoc_files:
|
|
221
207
|
- doc/release_notes/3.48.0.txt
|
222
208
|
- doc/release_notes/3.49.0.txt
|
223
209
|
- doc/release_notes/3.5.0.txt
|
210
|
+
- doc/release_notes/3.50.0.txt
|
211
|
+
- doc/release_notes/3.51.0.txt
|
212
|
+
- doc/release_notes/3.52.0.txt
|
213
|
+
- doc/release_notes/3.53.0.txt
|
224
214
|
- doc/release_notes/3.6.0.txt
|
225
215
|
- doc/release_notes/3.7.0.txt
|
226
216
|
- doc/release_notes/3.8.0.txt
|
@@ -277,6 +267,10 @@ files:
|
|
277
267
|
- doc/release_notes/3.48.0.txt
|
278
268
|
- doc/release_notes/3.49.0.txt
|
279
269
|
- doc/release_notes/3.5.0.txt
|
270
|
+
- doc/release_notes/3.50.0.txt
|
271
|
+
- doc/release_notes/3.51.0.txt
|
272
|
+
- doc/release_notes/3.52.0.txt
|
273
|
+
- doc/release_notes/3.53.0.txt
|
280
274
|
- doc/release_notes/3.6.0.txt
|
281
275
|
- doc/release_notes/3.7.0.txt
|
282
276
|
- doc/release_notes/3.8.0.txt
|
@@ -288,12 +282,14 @@ files:
|
|
288
282
|
- lib/roda/plugins/_before_hook.rb
|
289
283
|
- lib/roda/plugins/_optimized_matching.rb
|
290
284
|
- lib/roda/plugins/_symbol_regexp_matchers.rb
|
285
|
+
- lib/roda/plugins/additional_view_directories.rb
|
291
286
|
- lib/roda/plugins/all_verbs.rb
|
292
287
|
- lib/roda/plugins/assets.rb
|
293
288
|
- lib/roda/plugins/assets_preloading.rb
|
294
289
|
- lib/roda/plugins/backtracking_array.rb
|
295
290
|
- lib/roda/plugins/branch_locals.rb
|
296
291
|
- lib/roda/plugins/caching.rb
|
292
|
+
- lib/roda/plugins/capture_erb.rb
|
297
293
|
- lib/roda/plugins/chunked.rb
|
298
294
|
- lib/roda/plugins/class_level_routing.rb
|
299
295
|
- lib/roda/plugins/class_matchers.rb
|
@@ -329,6 +325,7 @@ files:
|
|
329
325
|
- lib/roda/plugins/hooks.rb
|
330
326
|
- lib/roda/plugins/host_authorization.rb
|
331
327
|
- lib/roda/plugins/indifferent_params.rb
|
328
|
+
- lib/roda/plugins/inject_erb.rb
|
332
329
|
- lib/roda/plugins/json.rb
|
333
330
|
- lib/roda/plugins/json_parser.rb
|
334
331
|
- lib/roda/plugins/mail_processor.rb
|
@@ -402,7 +399,7 @@ metadata:
|
|
402
399
|
bug_tracker_uri: https://github.com/jeremyevans/roda/issues
|
403
400
|
changelog_uri: http://roda.jeremyevans.net/rdoc/files/CHANGELOG.html
|
404
401
|
documentation_uri: http://roda.jeremyevans.net/documentation.html
|
405
|
-
mailing_list_uri: https://
|
402
|
+
mailing_list_uri: https://github.com/jeremyevans/roda/discussions
|
406
403
|
source_code_uri: https://github.com/jeremyevans/roda
|
407
404
|
post_install_message:
|
408
405
|
rdoc_options: []
|
@@ -419,7 +416,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
419
416
|
- !ruby/object:Gem::Version
|
420
417
|
version: '0'
|
421
418
|
requirements: []
|
422
|
-
rubygems_version: 3.
|
419
|
+
rubygems_version: 3.3.3
|
423
420
|
signing_key:
|
424
421
|
specification_version: 4
|
425
422
|
summary: Routing tree web toolkit
|