roda 3.21.0 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +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
|