roda 3.87.0 → 3.89.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|