roda 3.87.0 → 3.89.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/lib/roda/plugins/head.rb +1 -1
- data/lib/roda/plugins/json_parser.rb +20 -19
- data/lib/roda/plugins/mailer.rb +6 -0
- data/lib/roda/plugins/part.rb +76 -0
- data/lib/roda/plugins/render.rb +196 -40
- data/lib/roda/plugins/render_coverage.rb +22 -3
- data/lib/roda/plugins/render_each.rb +1 -1
- data/lib/roda/plugins/symbol_views.rb +4 -1
- data/lib/roda/plugins/view_options.rb +1 -1
- data/lib/roda/response.rb +4 -2
- data/lib/roda/version.rb +1 -1
- metadata +4 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c056e15afde950dcb27063296ba5b911fe3b900d16c121dd8833374731cdbaa
|
|
4
|
+
data.tar.gz: 95225a9c11b07979b50359df7451283eff570557c926f82c49cc34b67d1868fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e38354627d456f2b2bd593703d4ef64f5e934c071d439f1d9647cc8ef010de5fb463d001068ce2e06fd57b0cbccd926005d199b76761ebadefeda699937f5501
|
|
7
|
+
data.tar.gz: d542a024a5dd63bfa069baa38d2929bc0925d410641e303839f4a408139614249f223c3054f1f827550522aa21c0f52429184d3484001f7ed6996bbb9b366add
|
data/lib/roda/plugins/head.rb
CHANGED
|
@@ -53,27 +53,28 @@ class Roda
|
|
|
53
53
|
# parse the request body as JSON. Ignore an empty request body.
|
|
54
54
|
def POST
|
|
55
55
|
env = @env
|
|
56
|
-
if post_params =
|
|
57
|
-
post_params
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
if post_params = env["roda.json_params"]
|
|
57
|
+
return post_params
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
unless (input = env["rack.input"]) && (content_type = self.content_type) && content_type.include?('json')
|
|
61
|
+
return super
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
str = _read_json_input(input)
|
|
65
|
+
return super if str.empty?
|
|
66
|
+
begin
|
|
67
|
+
json_params = parse_json(str)
|
|
68
|
+
rescue
|
|
69
|
+
roda_class.opts[:json_parser_error_handler].call(self)
|
|
70
|
+
end
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
end
|
|
71
|
-
env["roda.json_params"] = json_params
|
|
72
|
-
env["rack.request.form_input"] = input
|
|
73
|
-
json_params
|
|
74
|
-
else
|
|
75
|
-
super
|
|
72
|
+
wrap = roda_class.opts[:json_parser_wrap]
|
|
73
|
+
if wrap == :always || (wrap == :unless_hash && !json_params.is_a?(Hash))
|
|
74
|
+
json_params = {"_json"=>json_params}
|
|
76
75
|
end
|
|
76
|
+
env["roda.json_params"] = json_params
|
|
77
|
+
json_params
|
|
77
78
|
end
|
|
78
79
|
|
|
79
80
|
private
|
data/lib/roda/plugins/mailer.rb
CHANGED
|
@@ -151,6 +151,9 @@ class Roda
|
|
|
151
151
|
mail
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
|
+
# :nocov:
|
|
155
|
+
ruby2_keywords(:mail) if respond_to?(:ruby2_keywords, true)
|
|
156
|
+
# :nocov:
|
|
154
157
|
|
|
155
158
|
# Calls +mail+ with given arguments and immediately sends the resulting mail.
|
|
156
159
|
def sendmail(*args)
|
|
@@ -158,6 +161,9 @@ class Roda
|
|
|
158
161
|
m.deliver
|
|
159
162
|
end
|
|
160
163
|
end
|
|
164
|
+
# :nocov:
|
|
165
|
+
ruby2_keywords(:sendmail) if respond_to?(:ruby2_keywords, true)
|
|
166
|
+
# :nocov:
|
|
161
167
|
end
|
|
162
168
|
|
|
163
169
|
module RequestMethods
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The part plugin adds a part method, which is a
|
|
7
|
+
# render-like method that treats all keywords as locals.
|
|
8
|
+
#
|
|
9
|
+
# # Can replace this:
|
|
10
|
+
# render(:template, locals: {foo: 'bar'})
|
|
11
|
+
#
|
|
12
|
+
# # With this:
|
|
13
|
+
# part(:template, foo: 'bar')
|
|
14
|
+
#
|
|
15
|
+
# On Ruby 2.7+, the part method takes a keyword splat, so you
|
|
16
|
+
# must pass keywords and not a positional hash for the locals.
|
|
17
|
+
#
|
|
18
|
+
# If you are using the :assume_fixed_locals render plugin option,
|
|
19
|
+
# template caching is enabled, you are using Ruby 3+, and you
|
|
20
|
+
# are freezing your Roda application, in addition to providing a
|
|
21
|
+
# simpler API, this also provides a significant performance
|
|
22
|
+
# improvement (more significant on Ruby 3.4+).
|
|
23
|
+
module Part
|
|
24
|
+
def self.load_dependencies(app)
|
|
25
|
+
app.plugin :render
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module ClassMethods
|
|
29
|
+
# When freezing, optimize the part method if assuming fixed locals
|
|
30
|
+
# and caching templates.
|
|
31
|
+
def freeze
|
|
32
|
+
if render_opts[:assume_fixed_locals] && !render_opts[:check_template_mtime]
|
|
33
|
+
include AssumeFixedLocalsInstanceMethods
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
module InstanceMethods
|
|
41
|
+
if RUBY_VERSION >= '2.7'
|
|
42
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
43
|
+
def part(template, **locals, &block)
|
|
44
|
+
render(template, :locals=>locals, &block)
|
|
45
|
+
end
|
|
46
|
+
RUBY
|
|
47
|
+
# :nocov:
|
|
48
|
+
else
|
|
49
|
+
def part(template, locals=OPTS, &block)
|
|
50
|
+
render(template, :locals=>locals, &block)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
# :nocov:
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module AssumeFixedLocalsInstanceMethods
|
|
57
|
+
# :nocov:
|
|
58
|
+
if RUBY_VERSION >= '3.0'
|
|
59
|
+
# :nocov:
|
|
60
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
61
|
+
def part(template, ...)
|
|
62
|
+
if optimized_method = _optimized_render_method_for_locals(template, OPTS)
|
|
63
|
+
send(optimized_method[0], ...)
|
|
64
|
+
else
|
|
65
|
+
super
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
RUBY
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
register_plugin(:part, Part)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
data/lib/roda/plugins/render.rb
CHANGED
|
@@ -48,6 +48,9 @@ class Roda
|
|
|
48
48
|
#
|
|
49
49
|
# :allowed_paths :: Set the template paths to allow. Attempts to render paths outside
|
|
50
50
|
# of these paths will raise an error. Defaults to the +:views+ directory.
|
|
51
|
+
# :assume_fixed_locals :: Set if you are sure all templates in your application use fixed locals
|
|
52
|
+
# to allow for additional optimization. This is ignored unless both
|
|
53
|
+
# compiled methods and fixed locals are not supported.
|
|
51
54
|
# :cache :: nil/false to explicitly disable permanent template caching. By default, permanent
|
|
52
55
|
# template caching is disabled by default if RACK_ENV is development. When permanent
|
|
53
56
|
# template caching is disabled, for templates with paths in the file system, the
|
|
@@ -118,6 +121,50 @@ class Roda
|
|
|
118
121
|
# have either +:template+, +:inline+, +:path+, or +:content+ (for +view+) as
|
|
119
122
|
# one of the keys.
|
|
120
123
|
#
|
|
124
|
+
# = Fixed Locals in Templates
|
|
125
|
+
#
|
|
126
|
+
# By default, you can pass any local variables to any templates. A separate
|
|
127
|
+
# template method is compiled for each combination of locals. This causes
|
|
128
|
+
# multiple issues:
|
|
129
|
+
#
|
|
130
|
+
# * It is inefficient, especially for large templates that are called with
|
|
131
|
+
# many combinations of locals.
|
|
132
|
+
# * It hides issues if unused local variable names are passed to the template
|
|
133
|
+
# * It does not support default values for local variables
|
|
134
|
+
# * It does not support required local variables
|
|
135
|
+
# * It does not support cases where you want to pass values via a keyword splat
|
|
136
|
+
# * It does not support named blocks
|
|
137
|
+
#
|
|
138
|
+
# If you are using Tilt 2.6+, you can used fixed locals in templates, by
|
|
139
|
+
# passing the appropriate options in :template_opts. For example, if you
|
|
140
|
+
# are using ERB templates, the recommended way to use the render plugin is to
|
|
141
|
+
# use the +:extract_fixed_locals+ and +:default_fixed_locals+ template options:
|
|
142
|
+
#
|
|
143
|
+
# plugin :render, template_opts: {extract_fixed_locals: true, default_fixed_locals: '()'}
|
|
144
|
+
#
|
|
145
|
+
# This will default templates to not allowing any local variables to be passed.
|
|
146
|
+
# If the template requires local variables, you can specify them using a magic
|
|
147
|
+
# comment in the template, such as:
|
|
148
|
+
#
|
|
149
|
+
# <%# locals(required_local:, optional_local: nil) %>
|
|
150
|
+
#
|
|
151
|
+
# The magic comment is used as method parameters when defining the compiled template
|
|
152
|
+
# method.
|
|
153
|
+
#
|
|
154
|
+
# For better debugging of issues with invalid keywords being passed to templates that
|
|
155
|
+
# have not been updated to support fixed locals, it can be helpful to set
|
|
156
|
+
# +:default_fixed_locals+ to use a single optional keyword argument
|
|
157
|
+
# <tt>'(_no_kw: nil)'</tt>. This makes the error message show which keywords
|
|
158
|
+
# were passed, instead of showing that the takes no arguments (if you use <tt>'()'</tt>),
|
|
159
|
+
# or that no keywords are accepted (if you pass <tt>(**nil)</tt>).
|
|
160
|
+
#
|
|
161
|
+
# If you are sure your application works with all templates using fixed locals,
|
|
162
|
+
# set the :assume_fixed_locals render plugin option, which will allow the plugin
|
|
163
|
+
# to optimize cache lookup for renders with locals, and avoid duplicate compiled
|
|
164
|
+
# methods for templates rendered both with and without locals.
|
|
165
|
+
#
|
|
166
|
+
# See Tilt's documentation for more information regarding fixed locals.
|
|
167
|
+
#
|
|
121
168
|
# = Speeding Up Template Rendering
|
|
122
169
|
#
|
|
123
170
|
# The render/view method calls are optimized for usage with a single symbol/string
|
|
@@ -131,6 +178,23 @@ class Roda
|
|
|
131
178
|
# the hash, making sure the +:cache_key+ is unique to the template you are
|
|
132
179
|
# rendering.
|
|
133
180
|
#
|
|
181
|
+
# = Recommended +template_opts+
|
|
182
|
+
#
|
|
183
|
+
# Here are the recommended values of :template_opts for new applications (a couple
|
|
184
|
+
# are Erubi-specific and can be ignored if you are using other templates engines):
|
|
185
|
+
#
|
|
186
|
+
# plugin :render,
|
|
187
|
+
# assume_fixed_locals: true, # Optimize plugin by assuming all templates use fixed locals
|
|
188
|
+
# template_opts: {
|
|
189
|
+
# scope_class: self, # Always uses current class as scope class for compiled templates
|
|
190
|
+
# freeze: true, # Freeze string literals in templates
|
|
191
|
+
# extract_fixed_locals: true, # Support fixed locals in templates
|
|
192
|
+
# default_fixed_locals: '()', # Default to templates not supporting local variables
|
|
193
|
+
# escape: true, # For Erubi templates, escapes <%= by default (use <%== for unescaped
|
|
194
|
+
# chain_appends: true, # For Erubi templates, improves performance
|
|
195
|
+
# skip_compiled_encoding_detection: true, # Unless you need encodings explicitly specified
|
|
196
|
+
# }
|
|
197
|
+
#
|
|
134
198
|
# = Accepting Template Blocks in Methods
|
|
135
199
|
#
|
|
136
200
|
# If you are used to Rails, you may be surprised that this type of template code
|
|
@@ -228,6 +292,19 @@ class Roda
|
|
|
228
292
|
([1, -2].include?(((compiled_method_arity = Tilt::Template.instance_method(:compiled_method).arity) rescue false)))
|
|
229
293
|
NO_CACHE = {:cache=>false}.freeze
|
|
230
294
|
COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' && tilt_compiled_method_support && ENV['RODA_RENDER_COMPILED_METHOD_SUPPORT'] != 'no'
|
|
295
|
+
FIXED_LOCALS_COMPILED_METHOD_SUPPORT = COMPILED_METHOD_SUPPORT && Tilt::Template.method_defined?(:fixed_locals?)
|
|
296
|
+
|
|
297
|
+
if FIXED_LOCALS_COMPILED_METHOD_SUPPORT
|
|
298
|
+
def self.tilt_template_fixed_locals?(template)
|
|
299
|
+
template.fixed_locals?
|
|
300
|
+
end
|
|
301
|
+
# :nocov:
|
|
302
|
+
else
|
|
303
|
+
def self.tilt_template_fixed_locals?(template)
|
|
304
|
+
false
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
# :nocov:
|
|
231
308
|
|
|
232
309
|
if compiled_method_arity == -2
|
|
233
310
|
def self.tilt_template_compiled_method(template, locals_keys, scope_class)
|
|
@@ -257,6 +334,7 @@ class Roda
|
|
|
257
334
|
opts[:allowed_paths] ||= [opts[:views]].freeze
|
|
258
335
|
opts[:allowed_paths] = opts[:allowed_paths].map{|f| app.expand_path(f, nil)}.uniq.freeze
|
|
259
336
|
opts[:check_paths] = true unless opts.has_key?(:check_paths)
|
|
337
|
+
opts[:assume_fixed_locals] &&= FIXED_LOCALS_COMPILED_METHOD_SUPPORT
|
|
260
338
|
|
|
261
339
|
unless opts.has_key?(:check_template_mtime)
|
|
262
340
|
opts[:check_template_mtime] = if opts[:cache] == false || opts[:explicit_cache]
|
|
@@ -385,6 +463,11 @@ class Roda
|
|
|
385
463
|
end
|
|
386
464
|
|
|
387
465
|
if COMPILED_METHOD_SUPPORT
|
|
466
|
+
# Whether the underlying template uses fixed locals.
|
|
467
|
+
def fixed_locals?
|
|
468
|
+
Render.tilt_template_fixed_locals?(@template)
|
|
469
|
+
end
|
|
470
|
+
|
|
388
471
|
# Compile a method in the given module with the given name that will
|
|
389
472
|
# call the compiled template method, updating the compiled template method
|
|
390
473
|
def define_compiled_method(roda_class, method_name, locals_keys=EMPTY_ARRAY)
|
|
@@ -403,6 +486,15 @@ class Roda
|
|
|
403
486
|
method_name
|
|
404
487
|
end
|
|
405
488
|
|
|
489
|
+
# Returns an appropriate value for the template method cache.
|
|
490
|
+
def define_compiled_method_cache_value(roda_class, method_name, locals_keys=EMPTY_ARRAY)
|
|
491
|
+
if compiled_method = define_compiled_method(roda_class, method_name, locals_keys)
|
|
492
|
+
[compiled_method, false].freeze
|
|
493
|
+
else
|
|
494
|
+
compiled_method
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
406
498
|
private
|
|
407
499
|
|
|
408
500
|
# Return the compiled method for the current template object.
|
|
@@ -422,7 +514,7 @@ class Roda
|
|
|
422
514
|
mod.send(:private, method_name)
|
|
423
515
|
end
|
|
424
516
|
|
|
425
|
-
|
|
517
|
+
_call_optimized_template_method([method_name, Render.tilt_template_fixed_locals?(template)], locals, &block)
|
|
426
518
|
end
|
|
427
519
|
end
|
|
428
520
|
end
|
|
@@ -450,6 +542,12 @@ class Roda
|
|
|
450
542
|
nil
|
|
451
543
|
end
|
|
452
544
|
|
|
545
|
+
# Optimize _call_optimized_template_method if you know all templates
|
|
546
|
+
# are going to be using fixed locals.
|
|
547
|
+
if render_opts[:assume_fixed_locals] && !render_opts[:check_template_mtime]
|
|
548
|
+
include AssumeFixedLocalsInstanceMethods
|
|
549
|
+
end
|
|
550
|
+
|
|
453
551
|
super
|
|
454
552
|
end
|
|
455
553
|
end
|
|
@@ -489,17 +587,17 @@ class Roda
|
|
|
489
587
|
def _freeze_layout_method
|
|
490
588
|
if render_opts[:layout]
|
|
491
589
|
instance = allocate
|
|
590
|
+
# This needs to be called even if COMPILED_METHOD_SUPPORT is not set,
|
|
591
|
+
# in order for the precompile_templates plugin to work correctly.
|
|
492
592
|
instance.send(:retrieve_template, instance.send(:view_layout_opts, OPTS))
|
|
493
593
|
|
|
494
|
-
if COMPILED_METHOD_SUPPORT
|
|
495
|
-
if (layout_template = render_opts[:optimize_layout]) && !opts[:render][:optimized_layout_method_created]
|
|
594
|
+
if COMPILED_METHOD_SUPPORT && (layout_template = render_opts[:optimize_layout]) && !opts[:render][:optimized_layout_method_created]
|
|
496
595
|
instance.send(:retrieve_template, :template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
|
|
497
596
|
layout_method = opts[:render][:template_method_cache][:_roda_layout]
|
|
498
597
|
define_method(:_layout_method){layout_method}
|
|
499
598
|
private :_layout_method
|
|
500
599
|
alias_method(:_layout_method, :_layout_method)
|
|
501
600
|
opts[:render] = opts[:render].merge(:optimized_layout_method_created=>true)
|
|
502
|
-
end
|
|
503
601
|
end
|
|
504
602
|
end
|
|
505
603
|
end
|
|
@@ -509,9 +607,9 @@ class Roda
|
|
|
509
607
|
# Render the given template. See Render for details.
|
|
510
608
|
def render(template, opts = (no_opts = true; optimized_template = _cached_template_method(template); OPTS), &block)
|
|
511
609
|
if optimized_template
|
|
512
|
-
|
|
610
|
+
_call_optimized_template_method(optimized_template, OPTS, &block)
|
|
513
611
|
elsif !no_opts && opts.length == 1 && (locals = opts[:locals]) && (optimized_template = _optimized_render_method_for_locals(template, locals))
|
|
514
|
-
|
|
612
|
+
_call_optimized_template_method(optimized_template, locals, &block)
|
|
515
613
|
else
|
|
516
614
|
opts = render_template_opts(template, opts)
|
|
517
615
|
retrieve_template(opts).render((opts[:scope]||self), (opts[:locals]||OPTS), &block)
|
|
@@ -534,7 +632,7 @@ class Roda
|
|
|
534
632
|
# and use it if so. This way avoids the extra conditional and local variable
|
|
535
633
|
# assignments in the next section.
|
|
536
634
|
if layout_method = _layout_method
|
|
537
|
-
return
|
|
635
|
+
return _call_optimized_template_method(layout_method, OPTS){content}
|
|
538
636
|
end
|
|
539
637
|
|
|
540
638
|
# If we have an optimized template method but no optimized layout method, create the
|
|
@@ -543,7 +641,7 @@ class Roda
|
|
|
543
641
|
if layout_template = self.class.opts[:render][:optimize_layout]
|
|
544
642
|
retrieve_template(:template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
|
|
545
643
|
if layout_method = _layout_method
|
|
546
|
-
return
|
|
644
|
+
return _call_optimized_template_method(layout_method, OPTS){content}
|
|
547
645
|
end
|
|
548
646
|
end
|
|
549
647
|
else
|
|
@@ -592,39 +690,54 @@ class Roda
|
|
|
592
690
|
# of the template render if the optimized path is used, or nil if the optimized
|
|
593
691
|
# path is not used and the long method needs to be used.
|
|
594
692
|
def _optimized_render_method_for_locals(template, locals)
|
|
693
|
+
render_opts = self.render_opts
|
|
595
694
|
return unless method_cache = render_opts[:template_method_cache]
|
|
596
695
|
|
|
597
|
-
|
|
598
|
-
key = [:_render_locals, template, locals_keys]
|
|
599
|
-
|
|
600
|
-
optimized_template = case template
|
|
696
|
+
case template
|
|
601
697
|
when String, Symbol
|
|
602
|
-
|
|
698
|
+
if fixed_locals = render_opts[:assume_fixed_locals]
|
|
699
|
+
key = template
|
|
700
|
+
if optimized_template = _cached_template_method_lookup(method_cache, key)
|
|
701
|
+
return optimized_template
|
|
702
|
+
end
|
|
703
|
+
else
|
|
704
|
+
key = [:_render_locals, template]
|
|
705
|
+
if optimized_template = _cached_template_method_lookup(method_cache, key)
|
|
706
|
+
# Fixed locals case
|
|
707
|
+
return optimized_template
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
locals_keys = locals.keys.sort
|
|
711
|
+
key << locals_keys
|
|
712
|
+
if optimized_template = _cached_template_method_lookup(method_cache, key)
|
|
713
|
+
# Regular locals case
|
|
714
|
+
return optimized_template
|
|
715
|
+
end
|
|
716
|
+
end
|
|
603
717
|
else
|
|
604
718
|
return
|
|
605
719
|
end
|
|
606
720
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
721
|
+
if method_cache_key = _cached_template_method_key(key)
|
|
722
|
+
template_obj = retrieve_template(render_template_opts(template, NO_CACHE))
|
|
723
|
+
unless fixed_locals
|
|
724
|
+
key.pop if fixed_locals = Render.tilt_template_fixed_locals?(template_obj)
|
|
725
|
+
key.freeze
|
|
726
|
+
end
|
|
727
|
+
method_name = :"_roda_template_locals_#{self.class.object_id}_#{method_cache_key}"
|
|
614
728
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
729
|
+
method_cache[method_cache_key] = case template_obj
|
|
730
|
+
when Render::TemplateMtimeWrapper
|
|
731
|
+
template_obj.define_compiled_method_cache_value(self.class, method_name, locals_keys)
|
|
732
|
+
else
|
|
733
|
+
begin
|
|
734
|
+
unbound_method = Render.tilt_template_compiled_method(template_obj, locals_keys, self.class)
|
|
735
|
+
rescue ::NotImplementedError
|
|
736
|
+
false
|
|
618
737
|
else
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
false
|
|
623
|
-
else
|
|
624
|
-
self.class::RodaCompiledTemplates.send(:define_method, method_name, unbound_method)
|
|
625
|
-
self.class::RodaCompiledTemplates.send(:private, method_name)
|
|
626
|
-
method_name
|
|
627
|
-
end
|
|
738
|
+
self.class::RodaCompiledTemplates.send(:define_method, method_name, unbound_method)
|
|
739
|
+
self.class::RodaCompiledTemplates.send(:private, method_name)
|
|
740
|
+
[method_name, fixed_locals].freeze
|
|
628
741
|
end
|
|
629
742
|
end
|
|
630
743
|
end
|
|
@@ -634,11 +747,47 @@ class Roda
|
|
|
634
747
|
# a single argument is passed to view.
|
|
635
748
|
def _optimized_view_content(template)
|
|
636
749
|
if optimized_template = _cached_template_method(template)
|
|
637
|
-
|
|
750
|
+
_call_optimized_template_method(optimized_template, OPTS)
|
|
638
751
|
elsif template.is_a?(Hash) && template.length == 1
|
|
639
752
|
template[:content]
|
|
640
753
|
end
|
|
641
754
|
end
|
|
755
|
+
|
|
756
|
+
if RUBY_VERSION >= '3'
|
|
757
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
758
|
+
def _call_optimized_template_method((meth, fixed_locals), locals, &block)
|
|
759
|
+
if fixed_locals
|
|
760
|
+
send(meth, **locals, &block)
|
|
761
|
+
else
|
|
762
|
+
send(meth, locals, &block)
|
|
763
|
+
end
|
|
764
|
+
end
|
|
765
|
+
RUBY
|
|
766
|
+
# :nocov:
|
|
767
|
+
elsif RUBY_VERSION >= '2'
|
|
768
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
769
|
+
def _call_optimized_template_method((meth, fixed_locals), locals, &block)
|
|
770
|
+
if fixed_locals
|
|
771
|
+
if locals.empty?
|
|
772
|
+
send(meth, &block)
|
|
773
|
+
else
|
|
774
|
+
send(meth, **locals, &block)
|
|
775
|
+
end
|
|
776
|
+
else
|
|
777
|
+
send(meth, locals, &block)
|
|
778
|
+
end
|
|
779
|
+
end
|
|
780
|
+
RUBY
|
|
781
|
+
else
|
|
782
|
+
# Call the optimized template method. This is designed to be used with the
|
|
783
|
+
# method cache, which caches the method name and whether the method uses
|
|
784
|
+
# fixed locals. Methods with fixed locals need to be called with a keyword
|
|
785
|
+
# splat.
|
|
786
|
+
def _call_optimized_template_method((meth, fixed_locals), locals, &block)
|
|
787
|
+
send(meth, locals, &block)
|
|
788
|
+
end
|
|
789
|
+
end
|
|
790
|
+
# :nocov:
|
|
642
791
|
else
|
|
643
792
|
def _cached_template_method(_)
|
|
644
793
|
nil
|
|
@@ -648,10 +797,6 @@ class Roda
|
|
|
648
797
|
nil
|
|
649
798
|
end
|
|
650
799
|
|
|
651
|
-
def _layout_method
|
|
652
|
-
nil
|
|
653
|
-
end
|
|
654
|
-
|
|
655
800
|
def _optimized_render_method_for_locals(_, _)
|
|
656
801
|
nil
|
|
657
802
|
end
|
|
@@ -661,7 +806,6 @@ class Roda
|
|
|
661
806
|
end
|
|
662
807
|
end
|
|
663
808
|
|
|
664
|
-
|
|
665
809
|
# Convert template options to single hash when rendering templates using render.
|
|
666
810
|
def render_template_opts(template, opts)
|
|
667
811
|
parse_template_opts(template, opts)
|
|
@@ -772,7 +916,7 @@ class Roda
|
|
|
772
916
|
|
|
773
917
|
if define_compiled_method
|
|
774
918
|
method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}"
|
|
775
|
-
method_cache[method_cache_key] = template.
|
|
919
|
+
method_cache[method_cache_key] = template.define_compiled_method_cache_value(self.class, method_name)
|
|
776
920
|
end
|
|
777
921
|
else
|
|
778
922
|
template = self.class.create_template(opts, template_opts)
|
|
@@ -786,7 +930,7 @@ class Roda
|
|
|
786
930
|
method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}"
|
|
787
931
|
self.class::RodaCompiledTemplates.send(:define_method, method_name, unbound_method)
|
|
788
932
|
self.class::RodaCompiledTemplates.send(:private, method_name)
|
|
789
|
-
method_cache[method_cache_key] = method_name
|
|
933
|
+
method_cache[method_cache_key] = [method_name, Render.tilt_template_fixed_locals?(template)].freeze
|
|
790
934
|
end
|
|
791
935
|
end
|
|
792
936
|
end
|
|
@@ -835,6 +979,18 @@ class Roda
|
|
|
835
979
|
end
|
|
836
980
|
end
|
|
837
981
|
end
|
|
982
|
+
|
|
983
|
+
module AssumeFixedLocalsInstanceMethods
|
|
984
|
+
# :nocov:
|
|
985
|
+
if RUBY_VERSION >= '3.0'
|
|
986
|
+
# :nocov:
|
|
987
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
|
988
|
+
def _call_optimized_template_method((meth,_), locals, &block)
|
|
989
|
+
send(meth, **locals, &block)
|
|
990
|
+
end
|
|
991
|
+
RUBY
|
|
992
|
+
end
|
|
993
|
+
end
|
|
838
994
|
end
|
|
839
995
|
|
|
840
996
|
register_plugin(:render, Render)
|
|
@@ -50,17 +50,36 @@ class Roda
|
|
|
50
50
|
# Set a compiled path on the created template, if the path for
|
|
51
51
|
# the template is in one of the allowed_views.
|
|
52
52
|
def create_template(opts, template_opts)
|
|
53
|
-
|
|
54
|
-
return template if opts[:template_block]
|
|
53
|
+
return super if opts[:template_block]
|
|
55
54
|
|
|
56
55
|
path = File.expand_path(opts[:path])
|
|
56
|
+
compiled_path = nil
|
|
57
57
|
(self.opts[:render_coverage_strip_paths] || render_opts[:allowed_paths]).each do |dir|
|
|
58
58
|
if path.start_with?(dir + '/')
|
|
59
|
-
|
|
59
|
+
compiled_path = File.join(self.opts[:render_coverage_dir], path[dir.length+1, 10000000].gsub('/', '-'))
|
|
60
60
|
break
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
# For Tilt 2.6+, when using :scope_class and fixed locals, must provide
|
|
65
|
+
# compiled path as option, since compilation happens during initalization
|
|
66
|
+
# in that case. This option should be ignored if the template does not
|
|
67
|
+
# support it, but some template class may break if the option is not
|
|
68
|
+
# handled, so for compatibility, only set the method if Tilt::Template
|
|
69
|
+
# will handle it.
|
|
70
|
+
if compiled_path && Tilt::Template.method_defined?(:fixed_locals?)
|
|
71
|
+
template_opts = template_opts.dup
|
|
72
|
+
template_opts[:compiled_path] = compiled_path
|
|
73
|
+
compiled_path = nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
template = super
|
|
77
|
+
|
|
78
|
+
# Set compiled path for template when using older tilt versions.
|
|
79
|
+
# :nocov:
|
|
80
|
+
template.compiled_path = compiled_path if compiled_path
|
|
81
|
+
# :nocov:
|
|
82
|
+
|
|
64
83
|
template
|
|
65
84
|
end
|
|
66
85
|
end
|
|
@@ -23,8 +23,11 @@ class Roda
|
|
|
23
23
|
# :foo
|
|
24
24
|
# end
|
|
25
25
|
module SymbolViews
|
|
26
|
-
def self.
|
|
26
|
+
def self.load_dependencies(app)
|
|
27
27
|
app.plugin :custom_block_results
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.configure(app)
|
|
28
31
|
app.opts[:custom_block_results][Symbol] = :view
|
|
29
32
|
end
|
|
30
33
|
end
|
data/lib/roda/response.rb
CHANGED
|
@@ -46,8 +46,6 @@ class Roda
|
|
|
46
46
|
|
|
47
47
|
# Instance methods for RodaResponse
|
|
48
48
|
module ResponseMethods
|
|
49
|
-
DEFAULT_HEADERS = {RodaResponseHeaders::CONTENT_TYPE => "text/html".freeze}.freeze
|
|
50
|
-
|
|
51
49
|
# The body for the current response.
|
|
52
50
|
attr_reader :body
|
|
53
51
|
|
|
@@ -179,11 +177,15 @@ class Roda
|
|
|
179
177
|
private
|
|
180
178
|
|
|
181
179
|
if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
|
|
180
|
+
DEFAULT_HEADERS = Rack::Headers[{RodaResponseHeaders::CONTENT_TYPE => "text/html".freeze}].freeze
|
|
181
|
+
|
|
182
182
|
# Use Rack::Headers for headers by default on Rack 3
|
|
183
183
|
def _initialize_headers
|
|
184
184
|
Rack::Headers.new
|
|
185
185
|
end
|
|
186
186
|
else
|
|
187
|
+
DEFAULT_HEADERS = {RodaResponseHeaders::CONTENT_TYPE => "text/html".freeze}.freeze
|
|
188
|
+
|
|
187
189
|
# Use plain hash for headers by default on Rack 1-2
|
|
188
190
|
def _initialize_headers
|
|
189
191
|
{}
|
data/lib/roda/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: roda
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.89.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremy Evans
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-02-12 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rack
|
|
@@ -150,7 +149,6 @@ dependencies:
|
|
|
150
149
|
- - ">="
|
|
151
150
|
- !ruby/object:Gem::Version
|
|
152
151
|
version: '0'
|
|
153
|
-
description:
|
|
154
152
|
email:
|
|
155
153
|
- code@jeremyevans.net
|
|
156
154
|
executables: []
|
|
@@ -255,6 +253,7 @@ files:
|
|
|
255
253
|
- lib/roda/plugins/padrino_render.rb
|
|
256
254
|
- lib/roda/plugins/param_matchers.rb
|
|
257
255
|
- lib/roda/plugins/params_capturing.rb
|
|
256
|
+
- lib/roda/plugins/part.rb
|
|
258
257
|
- lib/roda/plugins/partials.rb
|
|
259
258
|
- lib/roda/plugins/pass.rb
|
|
260
259
|
- lib/roda/plugins/path.rb
|
|
@@ -313,7 +312,6 @@ metadata:
|
|
|
313
312
|
documentation_uri: https://roda.jeremyevans.net/documentation.html
|
|
314
313
|
mailing_list_uri: https://github.com/jeremyevans/roda/discussions
|
|
315
314
|
source_code_uri: https://github.com/jeremyevans/roda
|
|
316
|
-
post_install_message:
|
|
317
315
|
rdoc_options: []
|
|
318
316
|
require_paths:
|
|
319
317
|
- lib
|
|
@@ -328,8 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
328
326
|
- !ruby/object:Gem::Version
|
|
329
327
|
version: '0'
|
|
330
328
|
requirements: []
|
|
331
|
-
rubygems_version: 3.
|
|
332
|
-
signing_key:
|
|
329
|
+
rubygems_version: 3.6.2
|
|
333
330
|
specification_version: 4
|
|
334
331
|
summary: Routing tree web toolkit
|
|
335
332
|
test_files: []
|