roda 3.21.0 → 3.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +4 -0
- data/doc/release_notes/3.22.0.txt +24 -0
- data/lib/roda/plugins/render.rb +132 -32
- data/lib/roda/plugins/render_locals.rb +10 -0
- data/lib/roda/plugins/sessions.rb +3 -2
- data/lib/roda/plugins/view_options.rb +28 -0
- data/lib/roda/version.rb +1 -1
- data/spec/plugin/render_spec.rb +158 -0
- data/spec/plugin/view_options_spec.rb +27 -0
- data/spec/views/a.rdoc +2 -0
- data/spec/views/about/comp_test.erb +1 -0
- data/spec/views/comp_layout.erb +1 -0
- data/spec/views/comp_test.erb +1 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c75151c856c93ac28e9089018a1d04f40f479782cc4d2e96099d4182d993d81a
|
4
|
+
data.tar.gz: 3190821d03128b656e573f8dc748fafcd753b55bfabd4d53c1c6c219ed0a340a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbf0bdcd577b6766483121f654b3e5139de674b81539fda0a43d949bb73d0092d7e280b1efd772409917a0f53a6fb877897126687060b4c6a14c8c9f5d152e75
|
7
|
+
data.tar.gz: 33fa800abbe118922d05db9712bc35910e7d633fbe4f224083c79f4289e8a269dcca90f31b2ac07aa0bece05c3957e5afa3f08bf14bea005a1b93242bcb317c5
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
= 3.22.0 (2019-07-12)
|
2
|
+
|
3
|
+
* Improve render performance up to 4x in the default case by calling compiled template methods directly (jeremyevans)
|
4
|
+
|
1
5
|
= 3.21.0 (2019-06-14)
|
2
6
|
|
3
7
|
* Cache compiled templates in development mode, until the template files are modified (jeremyevans)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
= Improvements
|
2
|
+
|
3
|
+
* The render/view methods in the render plugin, when called with
|
4
|
+
a single string/symbol argument (the most common case), are now
|
5
|
+
up to 2.5x/4x faster by directly calling compiled template methods.
|
6
|
+
This works by extracting the UnboundMethod objects that Tilt
|
7
|
+
creates, and defining real methods for them, then calling those
|
8
|
+
methods using send. This avoids most of the overhead of the render
|
9
|
+
and view methods. The compiled template methods are defined inside
|
10
|
+
a module included in the Roda app's class, so this support works
|
11
|
+
even if the Roda app itself is frozen.
|
12
|
+
|
13
|
+
Some plugins, such as render_locals, do not work with this
|
14
|
+
optimization, and disable the use of it. The view_options plugin
|
15
|
+
does work with this optimization if you are using set_view_subdir or
|
16
|
+
append_view_subdir, but not if using set_view_options or
|
17
|
+
set_layout_options.
|
18
|
+
|
19
|
+
This optimization depends on Ruby 2.3+ and Tilt 1.2+, and will not
|
20
|
+
be used on earlier versions, or if an API change in Tilt is
|
21
|
+
detected.
|
22
|
+
|
23
|
+
* Session deserialization is now slightly faster in the sessions
|
24
|
+
plugin.
|
data/lib/roda/plugins/render.rb
CHANGED
@@ -120,29 +120,27 @@ class Roda
|
|
120
120
|
#
|
121
121
|
# = Speeding Up Template Rendering
|
122
122
|
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
# if you do this, you need to make sure you choose a correct key.
|
123
|
+
# The render/view method calls are optimized for usage with a single symbol/string
|
124
|
+
# argument specifying the template name. So for fastest rendering, pass only a
|
125
|
+
# symbol/string to render/view.
|
127
126
|
#
|
128
|
-
# If
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
# set_view_options cache_key: r.path_info
|
133
|
-
#
|
134
|
-
# at the top of your route block. You can even do this if you do have paths
|
135
|
-
# that use more than one template, as long as you specify +:cache_key+
|
136
|
-
# specifically when rendering in those paths.
|
137
|
-
#
|
138
|
-
# If you use a single layout in your application, you can also make layout
|
139
|
-
# rendering faster by specifying +:cache_key+ inside the +:layout_opts+
|
140
|
-
# plugin option.
|
127
|
+
# If you must pass a hash to render/view, either as a second argument or as the
|
128
|
+
# only argument, you can speed things up by specifying a +:cache_key+ option in
|
129
|
+
# the hash, making sure the +:cache_key+ is unique to the template you are
|
130
|
+
# rendering.
|
141
131
|
module Render
|
132
|
+
# Support for using compiled methods directly requires Ruby 2.3 for the
|
133
|
+
# method binding to work, and Tilt 1.2 for Tilt::Template#compiled_method.
|
134
|
+
COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' &&
|
135
|
+
defined?(Tilt::VERSION) &&
|
136
|
+
Tilt::VERSION >= '1.2' &&
|
137
|
+
(Tilt::Template.instance_method(:compiled_method).arity rescue false) == 1
|
138
|
+
|
142
139
|
# Setup default rendering options. See Render for details.
|
143
140
|
def self.configure(app, opts=OPTS)
|
144
141
|
if app.opts[:render]
|
145
142
|
orig_cache = app.opts[:render][:cache]
|
143
|
+
orig_method_cache = app.opts[:render][:template_method_cache]
|
146
144
|
opts = app.opts[:render][:orig_opts].merge(opts)
|
147
145
|
end
|
148
146
|
app.opts[:render] = opts.dup
|
@@ -163,6 +161,20 @@ class Roda
|
|
163
161
|
end
|
164
162
|
end
|
165
163
|
|
164
|
+
if opts[:check_template_mtime]
|
165
|
+
opts.delete(:template_method_cache)
|
166
|
+
elsif COMPILED_METHOD_SUPPORT
|
167
|
+
opts[:template_method_cache] = orig_method_cache || (opts[:cache_class] || RodaCache).new
|
168
|
+
begin
|
169
|
+
app.const_get(:RodaCompiledTemplates, false)
|
170
|
+
rescue NameError
|
171
|
+
compiled_templates_module = Module.new
|
172
|
+
app.send(:include, compiled_templates_module)
|
173
|
+
app.const_set(:RodaCompiledTemplates, compiled_templates_module)
|
174
|
+
end
|
175
|
+
opts[:template_method_cache] = orig_method_cache || (opts[:cache_class] || RodaCache).new
|
176
|
+
end
|
177
|
+
|
166
178
|
opts[:cache] = orig_cache || (opts[:cache_class] || RodaCache).new
|
167
179
|
|
168
180
|
opts[:layout_opts] = (opts[:layout_opts] || {}).dup
|
@@ -182,6 +194,8 @@ class Roda
|
|
182
194
|
else
|
183
195
|
opts[:layout_opts][:template] = layout
|
184
196
|
end
|
197
|
+
|
198
|
+
opts[:optimize_layout] = (opts[:layout_opts][:template] if opts[:layout_opts].keys.sort == [:_is_layout, :template])
|
185
199
|
end
|
186
200
|
opts[:layout_opts].freeze
|
187
201
|
|
@@ -249,6 +263,9 @@ class Roda
|
|
249
263
|
def inherited(subclass)
|
250
264
|
super
|
251
265
|
opts = subclass.opts[:render] = subclass.opts[:render].dup
|
266
|
+
if COMPILED_METHOD_SUPPORT
|
267
|
+
opts[:template_method_cache] = (opts[:cache_class] || RodaCache).new
|
268
|
+
end
|
252
269
|
opts[:cache] = opts[:cache].dup
|
253
270
|
opts.freeze
|
254
271
|
end
|
@@ -261,9 +278,13 @@ class Roda
|
|
261
278
|
|
262
279
|
module InstanceMethods
|
263
280
|
# Render the given template. See Render for details.
|
264
|
-
def render(template, opts = OPTS, &block)
|
265
|
-
|
266
|
-
|
281
|
+
def render(template, opts = (optimized_template = _cached_template_method(template); OPTS), &block)
|
282
|
+
if optimized_template
|
283
|
+
send(optimized_template, OPTS, &block)
|
284
|
+
else
|
285
|
+
opts = render_template_opts(template, opts)
|
286
|
+
retrieve_template(opts).render((opts[:scope]||self), (opts[:locals]||OPTS), &block)
|
287
|
+
end
|
267
288
|
end
|
268
289
|
|
269
290
|
# Return the render options for the instance's class.
|
@@ -274,9 +295,26 @@ class Roda
|
|
274
295
|
# Render the given template. If there is a default layout
|
275
296
|
# for the class, take the result of the template rendering
|
276
297
|
# and render it inside the layout. See Render for details.
|
277
|
-
def view(template, opts=OPTS)
|
278
|
-
|
279
|
-
|
298
|
+
def view(template, opts = (optimized_template = _cached_template_method(template); OPTS))
|
299
|
+
if optimized_template
|
300
|
+
content = send(optimized_template, OPTS)
|
301
|
+
|
302
|
+
render_opts = self.class.opts[:render]
|
303
|
+
if layout_template = render_opts[:optimize_layout]
|
304
|
+
method_cache = render_opts[:template_method_cache]
|
305
|
+
unless layout_method = method_cache[:_roda_layout]
|
306
|
+
retrieve_template(:template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
|
307
|
+
layout_method = method_cache[:_roda_layout]
|
308
|
+
end
|
309
|
+
|
310
|
+
if layout_method
|
311
|
+
return send(layout_method, OPTS){content}
|
312
|
+
end
|
313
|
+
end
|
314
|
+
else
|
315
|
+
opts = parse_template_opts(template, opts)
|
316
|
+
content = opts[:content] || render_template(opts)
|
317
|
+
end
|
280
318
|
|
281
319
|
if layout_opts = view_layout_opts(opts)
|
282
320
|
content = render_template(layout_opts){content}
|
@@ -287,6 +325,41 @@ class Roda
|
|
287
325
|
|
288
326
|
private
|
289
327
|
|
328
|
+
if COMPILED_METHOD_SUPPORT
|
329
|
+
# If there is an instance method for the template, return the instance
|
330
|
+
# method symbol. This optimization is only used for render/view calls
|
331
|
+
# with a single string or symbol argument.
|
332
|
+
def _cached_template_method(template)
|
333
|
+
case template
|
334
|
+
when String, Symbol
|
335
|
+
if (method_cache = render_opts[:template_method_cache])
|
336
|
+
_cached_template_method_lookup(method_cache, template)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
# The key to use in the template method cache for the given template.
|
342
|
+
def _cached_template_method_key(template)
|
343
|
+
template
|
344
|
+
end
|
345
|
+
|
346
|
+
# Return the instance method symbol for the template in the method cache.
|
347
|
+
def _cached_template_method_lookup(method_cache, template)
|
348
|
+
method_cache[template]
|
349
|
+
end
|
350
|
+
else
|
351
|
+
# :nocov:
|
352
|
+
def _cached_template_method(template)
|
353
|
+
nil
|
354
|
+
end
|
355
|
+
|
356
|
+
def _cached_template_method_key(template)
|
357
|
+
nil
|
358
|
+
end
|
359
|
+
# :nocov:
|
360
|
+
end
|
361
|
+
|
362
|
+
|
290
363
|
# Convert template options to single hash when rendering templates using render.
|
291
364
|
def render_template_opts(template, opts)
|
292
365
|
parse_template_opts(template, opts)
|
@@ -313,7 +386,7 @@ class Roda
|
|
313
386
|
# Given the template name and options, set the template class, template path/content,
|
314
387
|
# template block, and locals to use for the render in the passed options.
|
315
388
|
def find_template(opts)
|
316
|
-
render_opts =
|
389
|
+
render_opts = self.class.opts[:render]
|
317
390
|
engine_override = opts[:engine]
|
318
391
|
engine = opts[:engine] ||= render_opts[:engine]
|
319
392
|
if content = opts[:inline]
|
@@ -332,13 +405,15 @@ class Roda
|
|
332
405
|
end
|
333
406
|
|
334
407
|
if cache
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
[
|
340
|
-
|
341
|
-
|
408
|
+
unless opts.has_key?(:cache_key)
|
409
|
+
template_block = opts[:template_block] unless content
|
410
|
+
template_opts = opts[:template_opts]
|
411
|
+
|
412
|
+
opts[:cache_key] = if template_class || engine_override || template_opts || template_block
|
413
|
+
[path, template_class, engine_override, template_opts, template_block]
|
414
|
+
else
|
415
|
+
path
|
416
|
+
end
|
342
417
|
end
|
343
418
|
else
|
344
419
|
opts.delete(:cache_key)
|
@@ -353,6 +428,9 @@ class Roda
|
|
353
428
|
if template.is_a?(Hash)
|
354
429
|
opts.merge!(template)
|
355
430
|
else
|
431
|
+
if opts.empty? && (key = _cached_template_method_key(template))
|
432
|
+
opts[:template_method_cache_key] = key
|
433
|
+
end
|
356
434
|
opts[:template] = template
|
357
435
|
opts
|
358
436
|
end
|
@@ -372,6 +450,7 @@ class Roda
|
|
372
450
|
end
|
373
451
|
cached_template(opts) do
|
374
452
|
opts = found_template_opts || find_template(opts)
|
453
|
+
render_opts = self.class.opts[:render]
|
375
454
|
template_opts = render_opts[:template_opts]
|
376
455
|
if engine_opts = render_opts[:engine_opts][opts[:engine]]
|
377
456
|
template_opts = template_opts.merge(engine_opts)
|
@@ -383,7 +462,28 @@ class Roda
|
|
383
462
|
if render_opts[:check_template_mtime] && !opts[:template_block] && !cache
|
384
463
|
TemplateMtimeWrapper.new(opts[:template_class], opts[:path], 1, template_opts)
|
385
464
|
else
|
386
|
-
opts[:template_class].new(opts[:path], 1, template_opts, &opts[:template_block])
|
465
|
+
template = opts[:template_class].new(opts[:path], 1, template_opts, &opts[:template_block])
|
466
|
+
|
467
|
+
if COMPILED_METHOD_SUPPORT &&
|
468
|
+
(method_cache_key = opts[:template_method_cache_key]) &&
|
469
|
+
(method_cache = render_opts[:template_method_cache]) &&
|
470
|
+
(method_cache[method_cache_key] != false) &&
|
471
|
+
!opts[:inline] &&
|
472
|
+
cache != false
|
473
|
+
|
474
|
+
begin
|
475
|
+
unbound_method = template.send(:compiled_method, OPTS)
|
476
|
+
rescue ::NotImplementedError
|
477
|
+
method_cache[method_cache_key] = false
|
478
|
+
else
|
479
|
+
method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}"
|
480
|
+
self.class::RodaCompiledTemplates.send(:define_method, method_name, unbound_method)
|
481
|
+
self.class::RodaCompiledTemplates.send(:private, method_name)
|
482
|
+
method_cache[method_cache_key] = method_name
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
template
|
387
487
|
end
|
388
488
|
end
|
389
489
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
+
require_relative 'render'
|
4
|
+
|
3
5
|
#
|
4
6
|
class Roda
|
5
7
|
module RodaPlugins
|
@@ -41,6 +43,14 @@ class Roda
|
|
41
43
|
module InstanceMethods
|
42
44
|
private
|
43
45
|
|
46
|
+
if Render::COMPILED_METHOD_SUPPORT
|
47
|
+
# Disable use of cached templates, since it assumes a render/view call with no
|
48
|
+
# options will have no locals.
|
49
|
+
def _cached_template_method(template)
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
44
54
|
def render_locals
|
45
55
|
opts[:render_locals]
|
46
56
|
end
|
@@ -394,10 +394,11 @@ class Roda
|
|
394
394
|
|
395
395
|
bitmap, created_at, updated_at = data.unpack('vVV')
|
396
396
|
padding_bytes = bitmap & PADDING_MASK
|
397
|
-
|
397
|
+
now = Time.now.to_i
|
398
|
+
if (max = opts[:max_seconds]) && now > created_at + max
|
398
399
|
return _session_serialization_error("Not returning session: maximum session time expired")
|
399
400
|
end
|
400
|
-
if (max = opts[:max_idle_seconds]) &&
|
401
|
+
if (max = opts[:max_idle_seconds]) && now > updated_at + max
|
401
402
|
return _session_serialization_error("Not returning session: maximum session idle time expired")
|
402
403
|
end
|
403
404
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
+
require_relative 'render'
|
4
|
+
|
3
5
|
#
|
4
6
|
class Roda
|
5
7
|
module RodaPlugins
|
@@ -124,6 +126,32 @@ class Roda
|
|
124
126
|
|
125
127
|
private
|
126
128
|
|
129
|
+
if Render::COMPILED_METHOD_SUPPORT
|
130
|
+
# Return nil if using custom view or layout options.
|
131
|
+
# If using a view subdir, prefix the template key with the subdir.
|
132
|
+
def _cached_template_method_key(template)
|
133
|
+
return if @_view_options || @_layout_options
|
134
|
+
|
135
|
+
if subdir = @_view_subdir
|
136
|
+
template = [subdir, template]
|
137
|
+
end
|
138
|
+
|
139
|
+
super
|
140
|
+
end
|
141
|
+
|
142
|
+
# Return nil if using custom view or layout options.
|
143
|
+
# If using a view subdir, prefix the template key with the subdir.
|
144
|
+
def _cached_template_method_lookup(method_cache, template)
|
145
|
+
return if @_view_options || @_layout_options
|
146
|
+
|
147
|
+
if subdir = @_view_subdir
|
148
|
+
template = [subdir, template]
|
149
|
+
end
|
150
|
+
|
151
|
+
super
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
127
155
|
# If view options or locals have been set and this
|
128
156
|
# template isn't a layout template, merge the options
|
129
157
|
# and locals into the returned hash.
|
data/lib/roda/version.rb
CHANGED
data/spec/plugin/render_spec.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require_relative "../spec_helper"
|
2
2
|
|
3
3
|
begin
|
4
|
+
require 'tilt'
|
4
5
|
require 'tilt/erb'
|
5
6
|
require 'tilt/string'
|
7
|
+
require_relative '../../lib/roda/plugins/render'
|
6
8
|
rescue LoadError
|
7
9
|
warn "tilt not installed, skipping render plugin test"
|
8
10
|
else
|
@@ -258,6 +260,162 @@ describe "render plugin" do
|
|
258
260
|
app.render_opts[:views].must_equal File.join(Dir.pwd, 'bar')
|
259
261
|
end
|
260
262
|
|
263
|
+
if Roda::RodaPlugins::Render::COMPILED_METHOD_SUPPORT
|
264
|
+
it "does not cache template renders when using a template library that doesn't support it" do
|
265
|
+
begin
|
266
|
+
require 'tilt/rdoc'
|
267
|
+
rescue
|
268
|
+
next
|
269
|
+
end
|
270
|
+
|
271
|
+
app(:bare) do
|
272
|
+
plugin :render, :views=>'spec/views', :engine=>'rdoc'
|
273
|
+
route do
|
274
|
+
render('a')
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
app.render_opts[:template_method_cache]['a'].must_be_nil
|
279
|
+
body.strip.must_equal "<p># a # * b</p>"
|
280
|
+
app.render_opts[:template_method_cache]['a'].must_equal false
|
281
|
+
body.strip.must_equal "<p># a # * b</p>"
|
282
|
+
app.render_opts[:template_method_cache]['a'].must_equal false
|
283
|
+
body.strip.must_equal "<p># a # * b</p>"
|
284
|
+
app.render_opts[:template_method_cache]['a'].must_equal false
|
285
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 0
|
286
|
+
end
|
287
|
+
|
288
|
+
['comp_test', :comp_test].each do |template|
|
289
|
+
it "does not cache template renders when given a hash" do
|
290
|
+
app(:bare) do
|
291
|
+
plugin :render, :views=>'spec/views'
|
292
|
+
route do
|
293
|
+
render(:template=>template)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
298
|
+
body.strip.must_equal "ct"
|
299
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
300
|
+
body.strip.must_equal "ct"
|
301
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
302
|
+
body.strip.must_equal "ct"
|
303
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
304
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 0
|
305
|
+
end
|
306
|
+
|
307
|
+
it "caches template renders when given a #{template.class}" do
|
308
|
+
app(:bare) do
|
309
|
+
plugin :render, :views=>'spec/views'
|
310
|
+
route do
|
311
|
+
render(template)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
316
|
+
body.strip.must_equal "ct"
|
317
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
318
|
+
body.strip.must_equal "ct"
|
319
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
320
|
+
body.strip.must_equal "ct"
|
321
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
322
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 1
|
323
|
+
end
|
324
|
+
|
325
|
+
it "does not cache template views or layout when given a hash" do
|
326
|
+
app(:bare) do
|
327
|
+
layout = template.to_s.sub('test', 'layout')
|
328
|
+
layout = layout.to_sym if template.is_a?(Symbol)
|
329
|
+
plugin :render, :views=>'spec/views', :layout=>layout
|
330
|
+
route do
|
331
|
+
view(:template=>template)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
336
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
337
|
+
body.strip.must_equal "act\nb"
|
338
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
339
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
340
|
+
body.strip.must_equal "act\nb"
|
341
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
342
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
343
|
+
body.strip.must_equal "act\nb"
|
344
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
345
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
346
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 0
|
347
|
+
end
|
348
|
+
|
349
|
+
it "caches template views with layout when given a #{template.class}" do
|
350
|
+
app(:bare) do
|
351
|
+
layout = template.to_s.sub('test', 'layout')
|
352
|
+
layout = layout.to_sym if template.is_a?(Symbol)
|
353
|
+
plugin :render, :views=>'spec/views', :layout=>layout
|
354
|
+
route do
|
355
|
+
view(template)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
360
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
361
|
+
body.strip.must_equal "act\nb"
|
362
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
363
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
364
|
+
body.strip.must_equal "act\nb"
|
365
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
366
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_kind_of(Symbol)
|
367
|
+
body.strip.must_equal "act\nb"
|
368
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
369
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_kind_of(Symbol)
|
370
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 2
|
371
|
+
end
|
372
|
+
|
373
|
+
it "caches template views without layout when additional layout options given when given a #{template.class}" do
|
374
|
+
app(:bare) do
|
375
|
+
plugin :render, :views=>'spec/views', :layout=>nil
|
376
|
+
route do
|
377
|
+
view(template)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
382
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
383
|
+
body.strip.must_equal "ct"
|
384
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
385
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
386
|
+
body.strip.must_equal "ct"
|
387
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
388
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
389
|
+
body.strip.must_equal "ct"
|
390
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
391
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
392
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 1
|
393
|
+
end
|
394
|
+
|
395
|
+
it "caches template views without layout when additional layout options given when given a #{template.class}" do
|
396
|
+
app(:bare) do
|
397
|
+
plugin :render, :views=>'spec/views', :layout_opts=>{:locals=>{:title=>"Home"}}
|
398
|
+
route do
|
399
|
+
view(template)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
app.render_opts[:template_method_cache][template].must_be_nil
|
404
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
405
|
+
body.strip.must_equal "<title>Roda: Home</title>\nct"
|
406
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
407
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
408
|
+
body.strip.must_equal "<title>Roda: Home</title>\nct"
|
409
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
410
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
411
|
+
body.strip.must_equal "<title>Roda: Home</title>\nct"
|
412
|
+
app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
|
413
|
+
app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
|
414
|
+
app::RodaCompiledTemplates.private_instance_methods.length.must_equal 1
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
261
419
|
it "inline layouts and inline views" do
|
262
420
|
app(:render) do
|
263
421
|
view({:inline=>'bar'}, :layout=>{:inline=>'Foo: <%= yield %>'})
|
@@ -21,12 +21,23 @@ describe "view_options plugin view subdirs" do
|
|
21
21
|
|
22
22
|
r.on "about" do
|
23
23
|
append_view_subdir 'views'
|
24
|
+
r.on 'test' do
|
25
|
+
append_view_subdir 'about'
|
26
|
+
r.is('view'){view("comp_test")}
|
27
|
+
r.is{render("comp_test")}
|
28
|
+
end
|
24
29
|
render("about", :locals=>{:title => "About Roda"})
|
25
30
|
end
|
26
31
|
|
27
32
|
r.on "path" do
|
28
33
|
render('spec/views/about', :locals=>{:title => "Path"}, :layout_opts=>{:locals=>{:title=>"Home"}})
|
29
34
|
end
|
35
|
+
|
36
|
+
r.on 'test' do
|
37
|
+
set_view_subdir 'spec/views'
|
38
|
+
r.is('view'){view("comp_test")}
|
39
|
+
r.is{render("comp_test")}
|
40
|
+
end
|
30
41
|
end
|
31
42
|
end
|
32
43
|
end
|
@@ -42,6 +53,22 @@ describe "view_options plugin view subdirs" do
|
|
42
53
|
it "should not change behavior when subdir is not set" do
|
43
54
|
body("/path").strip.must_equal "<h1>Path</h1>"
|
44
55
|
end
|
56
|
+
|
57
|
+
it "should handle template compilation correctly" do
|
58
|
+
@app.plugin :render, :layout=>'./spec/views/comp_layout'
|
59
|
+
3.times do
|
60
|
+
body("/test").strip.must_equal "ct"
|
61
|
+
body("/about/test").strip.must_equal "about-ct"
|
62
|
+
body("/test/view").strip.must_equal "act\nb"
|
63
|
+
body("/about/test/view").strip.must_equal "aabout-ct\nb"
|
64
|
+
end
|
65
|
+
if Roda::RodaPlugins::Render::COMPILED_METHOD_SUPPORT
|
66
|
+
method_cache = @app.opts[:render][:template_method_cache]
|
67
|
+
method_cache[['spec/views', 'comp_test']].must_be_kind_of(Symbol)
|
68
|
+
method_cache[['spec/views/about', 'comp_test']].must_be_kind_of(Symbol)
|
69
|
+
method_cache[:_roda_layout].must_be_kind_of(Symbol)
|
70
|
+
end
|
71
|
+
end
|
45
72
|
end
|
46
73
|
|
47
74
|
describe "view_options plugin" do
|
data/spec/views/a.rdoc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
about-ct
|
@@ -0,0 +1 @@
|
|
1
|
+
a<%= yield %>b
|
@@ -0,0 +1 @@
|
|
1
|
+
ct
|
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.22.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: 2019-
|
11
|
+
date: 2019-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -218,6 +218,7 @@ extra_rdoc_files:
|
|
218
218
|
- doc/release_notes/3.19.0.txt
|
219
219
|
- doc/release_notes/3.20.0.txt
|
220
220
|
- doc/release_notes/3.21.0.txt
|
221
|
+
- doc/release_notes/3.22.0.txt
|
221
222
|
files:
|
222
223
|
- CHANGELOG
|
223
224
|
- MIT-LICENSE
|
@@ -275,6 +276,7 @@ files:
|
|
275
276
|
- doc/release_notes/3.2.0.txt
|
276
277
|
- doc/release_notes/3.20.0.txt
|
277
278
|
- doc/release_notes/3.21.0.txt
|
279
|
+
- doc/release_notes/3.22.0.txt
|
278
280
|
- doc/release_notes/3.3.0.txt
|
279
281
|
- doc/release_notes/3.4.0.txt
|
280
282
|
- doc/release_notes/3.5.0.txt
|
@@ -500,13 +502,17 @@ files:
|
|
500
502
|
- spec/version_spec.rb
|
501
503
|
- spec/views/_test.erb
|
502
504
|
- spec/views/a.erb
|
505
|
+
- spec/views/a.rdoc
|
503
506
|
- spec/views/about.erb
|
504
507
|
- spec/views/about.str
|
505
508
|
- spec/views/about/_test.css.gz
|
506
509
|
- spec/views/about/_test.erb
|
507
510
|
- spec/views/about/_test.erb.gz
|
511
|
+
- spec/views/about/comp_test.erb
|
508
512
|
- spec/views/b.erb
|
509
513
|
- spec/views/c.erb
|
514
|
+
- spec/views/comp_layout.erb
|
515
|
+
- spec/views/comp_test.erb
|
510
516
|
- spec/views/content-yield.erb
|
511
517
|
- spec/views/home.erb
|
512
518
|
- spec/views/home.str
|