roda 3.22.0 → 3.23.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c75151c856c93ac28e9089018a1d04f40f479782cc4d2e96099d4182d993d81a
4
- data.tar.gz: 3190821d03128b656e573f8dc748fafcd753b55bfabd4d53c1c6c219ed0a340a
3
+ metadata.gz: 2229b19a7b47a63c8f953c9a225f094d9b6c1120893629e30fea16fe189c8462
4
+ data.tar.gz: 341a5222c9bdf0cdc1aa56b654dd1accdce94257a5f9a756c8a8d37cf5bd5af8
5
5
  SHA512:
6
- metadata.gz: cbf0bdcd577b6766483121f654b3e5139de674b81539fda0a43d949bb73d0092d7e280b1efd772409917a0f53a6fb877897126687060b4c6a14c8c9f5d152e75
7
- data.tar.gz: 33fa800abbe118922d05db9712bc35910e7d633fbe4f224083c79f4289e8a269dcca90f31b2ac07aa0bece05c3957e5afa3f08bf14bea005a1b93242bcb317c5
6
+ metadata.gz: c996fa5a43603f429fb061c84585a84dbe97719032893f3ae1fff22dcd8056fb1c71fb8fa103ea46fca1a50cbaf6156139e9b1ee03ac1151e7a33d576d08b724
7
+ data.tar.gz: 8eff9c58e5dc39d40e18445bb33a4dcba019034975c110382a9f143021ddaf6920b8e783cc031be07f431a295e2b973ed750cf9f71e064c0796822e51faa6145
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ = 3.23.0 (2019-08-13)
2
+
3
+ * Make roda/session_middleware work if type_routing plugin is loaded into Roda itself (jeremyevans) (#169)
4
+
5
+ * Handle requests with nothing before extension in the path in the type_routing plugin (jeremyevans) (#168)
6
+
7
+ * Always show line number in exception_page output in exception_page plugin (jeremyevans)
8
+
9
+ * Improve render/view performance up to 2x in development mode in the default case by calling compiled template methods directly (jeremyevans)
10
+
1
11
  = 3.22.0 (2019-07-12)
2
12
 
3
13
  * Improve render performance up to 4x in the default case by calling compiled template methods directly (jeremyevans)
@@ -0,0 +1,28 @@
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 2x faster in cache: false mode by directly calling compiled
6
+ template methods. This takes the performance increase in 3.22.0
7
+ and applies it to cache: false mode in addition to cache: true
8
+ mode. If the template file has changed, the compiled method is
9
+ removed, and a new compiled method replaces it.
10
+
11
+ * Template modification detection in the render plugin now uses a
12
+ faster check for modification, which also avoids a race condition.
13
+
14
+ * The type_routing plugin now handles requests with nothing but the
15
+ extension in the request path. This fixes cases when you have
16
+ one app partially route a request, and send the request to another
17
+ app, and that app uses the type_routing plugin and has an r.is
18
+ call at the root level.
19
+
20
+ * The roda/session_middleware middleware now works correctly if the
21
+ type_routing plugin is loaded into Roda itself (as opposed to a
22
+ Roda subclass).
23
+
24
+ * The exception_page plugin now always shows the line number for
25
+ each line. Previously, it only showed the line number if it was
26
+ showing the content of the line, which complicated debugging in
27
+ cases where the content of the line was no longer retrievable
28
+ due to file system permissions or restrictions (e.g. chroot).
@@ -340,9 +340,12 @@ class Roda
340
340
  end
341
341
 
342
342
  # Load a new plugin into the current class. A plugin can be a module
343
- # which is used directly, or a symbol represented a registered plugin
343
+ # which is used directly, or a symbol representing a registered plugin
344
344
  # which will be required and then used. Returns nil.
345
345
  #
346
+ # Note that you should not load plugins into a Roda class after the
347
+ # class has been subclassed, as doing so can break the subclasses.
348
+ #
346
349
  # Roda.plugin PluginModule
347
350
  # Roda.plugin :csrf
348
351
  def plugin(plugin, *args, &block)
@@ -330,7 +330,7 @@ END
330
330
  <ul class="traceback">
331
331
  #{frames.map{|frame| id = frame[:id]; (<<END1)}.join
332
332
  <li class="frame">
333
- <code>#{h frame[:filename]}</code>: in <code>#{h frame[:function]}</code>
333
+ <code>#{h frame[:filename]}:#{frame[:lineno]}</code> in <code>#{h frame[:function]}</code>
334
334
 
335
335
  #{frame[:context_line] ? (<<END2) : '</li>'
336
336
  <div class="context" id="c#{id}">
@@ -161,20 +161,14 @@ class Roda
161
161
  end
162
162
  end
163
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
164
+ begin
165
+ app.const_get(:RodaCompiledTemplates, false)
166
+ rescue NameError
167
+ compiled_templates_module = Module.new
168
+ app.send(:include, compiled_templates_module)
169
+ app.const_set(:RodaCompiledTemplates, compiled_templates_module)
176
170
  end
177
-
171
+ opts[:template_method_cache] = orig_method_cache || (opts[:cache_class] || RodaCache).new
178
172
  opts[:cache] = orig_cache || (opts[:cache_class] || RodaCache).new
179
173
 
180
174
  opts[:layout_opts] = (opts[:layout_opts] || {}).dup
@@ -244,15 +238,68 @@ class Roda
244
238
  # If the template file exists and the modification time has
245
239
  # changed, rebuild the template file, then call render on it.
246
240
  def render(*args, &block)
247
- if File.file?(path = @path)
248
- mtime = File.mtime(path)
241
+ modified?
242
+ @template.render(*args, &block)
243
+ end
244
+
245
+ # If the template file has been updated, return true and update
246
+ # the template object and the modification time. Other return false.
247
+ def modified?
248
+ begin
249
+ mtime = File.mtime(path = @path)
250
+ rescue
251
+ # ignore errors
252
+ else
249
253
  if mtime != @mtime
250
254
  @mtime = mtime
251
255
  @template = @template_class.new(path, *@template_args)
256
+ return true
252
257
  end
253
258
  end
254
259
 
255
- @template.render(*args, &block)
260
+ false
261
+ end
262
+
263
+ if COMPILED_METHOD_SUPPORT
264
+ # Compile a method in the given module with the given name that will
265
+ # call the compiled template method, updating the compiled template method
266
+ def define_compiled_method(roda_class, method_name)
267
+ mod = roda_class::RodaCompiledTemplates
268
+ internal_method_name = :"_#{method_name}"
269
+ begin
270
+ mod.send(:define_method, internal_method_name, send(:compiled_method, OPTS))
271
+ rescue ::NotImplementedError
272
+ return false
273
+ end
274
+
275
+ mod.send(:private, internal_method_name)
276
+ mod.send(:define_method, method_name, &compiled_method_lambda(self, roda_class, internal_method_name))
277
+ mod.send(:private, method_name)
278
+
279
+ method_name
280
+ end
281
+
282
+ private
283
+
284
+ # Return the compiled method for the current template object.
285
+ def compiled_method(_)
286
+ @template.send(:compiled_method, OPTS)
287
+ end
288
+
289
+ # Return the lambda used to define the compiled template method. This
290
+ # is separated into its own method so the lambda does not capture any
291
+ # unnecessary local variables
292
+ def compiled_method_lambda(template, roda_class, method_name)
293
+ mod = roda_class::RodaCompiledTemplates
294
+ lambda do |_, &block|
295
+ if template.modified?
296
+ mod.send(:define_method, method_name, template.send(:compiled_method, OPTS))
297
+ mod.send(:private, method_name)
298
+ end
299
+
300
+ send(method_name, OPTS, &block)
301
+ end
302
+ end
256
303
  end
257
304
  end
258
305
 
@@ -459,18 +506,23 @@ class Roda
459
506
  template_opts = template_opts.merge(current_template_opts)
460
507
  end
461
508
 
509
+ define_compiled_method = COMPILED_METHOD_SUPPORT &&
510
+ (method_cache_key = opts[:template_method_cache_key]) &&
511
+ (method_cache = render_opts[:template_method_cache]) &&
512
+ (method_cache[method_cache_key] != false) &&
513
+ !opts[:inline]
514
+
462
515
  if render_opts[:check_template_mtime] && !opts[:template_block] && !cache
463
- TemplateMtimeWrapper.new(opts[:template_class], opts[:path], 1, template_opts)
516
+ template = TemplateMtimeWrapper.new(opts[:template_class], opts[:path], 1, template_opts)
517
+
518
+ if define_compiled_method
519
+ method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}"
520
+ method_cache[method_cache_key] = template.define_compiled_method(self.class, method_name)
521
+ end
464
522
  else
465
523
  template = opts[:template_class].new(opts[:path], 1, template_opts, &opts[:template_block])
466
524
 
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
-
525
+ if define_compiled_method && cache != false
474
526
  begin
475
527
  unbound_method = template.send(:compiled_method, OPTS)
476
528
  rescue ::NotImplementedError
@@ -482,9 +534,9 @@ class Roda
482
534
  method_cache[method_cache_key] = method_name
483
535
  end
484
536
  end
485
-
486
- template
487
537
  end
538
+
539
+ template
488
540
  end
489
541
  end
490
542
 
@@ -131,7 +131,7 @@ class Roda
131
131
  mimes.freeze
132
132
 
133
133
  type_keys = config[:types].keys
134
- config[:extension_regexp] = /(.+?)\.(#{Regexp.union(type_keys.map(&:to_s))})\z/
134
+ config[:extension_regexp] = /(.*?)\.(#{Regexp.union(type_keys.map(&:to_s))})\z/
135
135
 
136
136
  type_keys.each do |type|
137
137
  app::RodaRequest.send(:define_method, type) do |&block|
@@ -150,11 +150,18 @@ class RodaSessionMiddleware
150
150
  end
151
151
  end
152
152
 
153
+ module RequestMethods
154
+ # Work around for if type_routing plugin is loaded into Roda class itself.
155
+ def _remaining_path(_)
156
+ end
157
+ end
158
+
153
159
  # Setup the middleware, passing +opts+ as the Roda sessions plugin options.
154
160
  def initialize(app, opts)
155
161
  mid = Class.new(Roda)
156
162
  mid.plugin :sessions, opts
157
163
  @req_class = mid::RodaRequest
164
+ @req_class.send(:include, RequestMethods)
158
165
  @app = app
159
166
  end
160
167
 
@@ -4,7 +4,7 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 22
7
+ RodaMinorVersion = 23
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
@@ -139,6 +139,17 @@ describe "exception_page plugin" do
139
139
  body.wont_include 'id="c0"'
140
140
  end
141
141
 
142
+ it "should still show line numbers if the line content cannot be displayed" do
143
+ app(:exception_page) do |r|
144
+ instance_eval('raise "foo"', 'foo-bar.rb', 4200+42) rescue exception_page($!)
145
+ end
146
+ body = body('HTTP_ACCEPT'=>'text/html')
147
+ body.must_include "RuntimeError: foo"
148
+ body.must_include "foo-bar.rb:#{4200+42}"
149
+ body.must_include __FILE__
150
+ body.wont_include 'id="c0"'
151
+ end
152
+
142
153
  it "should serve exception page assets" do
143
154
  app(:exception_page) do |r|
144
155
  r.exception_page_assets
@@ -261,157 +261,160 @@ describe "render plugin" do
261
261
  end
262
262
 
263
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')
264
+ [true, false].each do |cache_plugin_option|
265
+ multiplier = cache_plugin_option ? 1 : 2
266
+ it "does not cache template renders when using a template library that doesn't support it with plugin option :cache=>#{cache_plugin_option}" do
267
+ begin
268
+ require 'tilt/rdoc'
269
+ rescue
270
+ next
275
271
  end
276
- end
277
272
 
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
273
  app(:bare) do
291
- plugin :render, :views=>'spec/views'
274
+ plugin :render, :views=>'spec/views', :engine=>'rdoc', :cache=>cache_plugin_option
292
275
  route do
293
- render(:template=>template)
276
+ render('a')
294
277
  end
295
278
  end
296
279
 
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
280
+ app.render_opts[:template_method_cache]['a'].must_be_nil
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
+ body.strip.must_equal "<p># a # * b</p>"
286
+ app.render_opts[:template_method_cache]['a'].must_equal false
304
287
  app::RodaCompiledTemplates.private_instance_methods.length.must_equal 0
305
288
  end
306
289
 
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)
290
+ ['comp_test', :comp_test].each do |template|
291
+ it "does not cache template renders when given a hash with #{template.class} value with plugin option :cache=>#{cache_plugin_option}" do
292
+ app(:bare) do
293
+ plugin :render, :views=>'spec/views', :cache=>cache_plugin_option
294
+ route do
295
+ render(:template=>template)
296
+ end
312
297
  end
313
- end
314
298
 
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
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
+ body.strip.must_equal "ct"
305
+ app.render_opts[:template_method_cache][template].must_be_nil
306
+ app::RodaCompiledTemplates.private_instance_methods.length.must_equal 0
307
+ end
324
308
 
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)
309
+ it "caches template renders when given a #{template.class} with plugin option :cache=>#{cache_plugin_option}" do
310
+ app(:bare) do
311
+ plugin :render, :views=>'spec/views', :cache=>cache_plugin_option
312
+ route do
313
+ render(template)
314
+ end
332
315
  end
333
- end
334
316
 
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
317
+ app.render_opts[:template_method_cache][template].must_be_nil
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
+ body.strip.must_equal "ct"
323
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
324
+ app::RodaCompiledTemplates.private_instance_methods.length.must_equal multiplier
325
+ end
348
326
 
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)
327
+ it "does not cache template views or layout when given a hash with #{template.class} value with plugin option :cache=>#{cache_plugin_option}" do
328
+ app(:bare) do
329
+ layout = template.to_s.sub('test', 'layout')
330
+ layout = layout.to_sym if template.is_a?(Symbol)
331
+ plugin :render, :views=>'spec/views', :layout=>layout, :cache=>cache_plugin_option
332
+ route do
333
+ view(:template=>template)
334
+ end
356
335
  end
336
+
337
+ app.render_opts[:template_method_cache][template].must_be_nil
338
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
339
+ body.strip.must_equal "act\nb"
340
+ app.render_opts[:template_method_cache][template].must_be_nil
341
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
342
+ body.strip.must_equal "act\nb"
343
+ app.render_opts[:template_method_cache][template].must_be_nil
344
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
345
+ body.strip.must_equal "act\nb"
346
+ app.render_opts[:template_method_cache][template].must_be_nil
347
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
348
+ app::RodaCompiledTemplates.private_instance_methods.length.must_equal 0
357
349
  end
358
350
 
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)
351
+ it "caches template views with layout when given a #{template.class} with plugin option :cache=>#{cache_plugin_option}" do
352
+ app(:bare) do
353
+ layout = template.to_s.sub('test', 'layout')
354
+ layout = layout.to_sym if template.is_a?(Symbol)
355
+ plugin :render, :views=>'spec/views', :layout=>layout, :cache=>cache_plugin_option
356
+ route do
357
+ view(template)
358
+ end
378
359
  end
360
+
361
+ app.render_opts[:template_method_cache][template].must_be_nil
362
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
363
+ body.strip.must_equal "act\nb"
364
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
365
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
366
+ body.strip.must_equal "act\nb"
367
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
368
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_kind_of(Symbol)
369
+ body.strip.must_equal "act\nb"
370
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
371
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_kind_of(Symbol)
372
+ app::RodaCompiledTemplates.private_instance_methods.length.must_equal(2*multiplier)
379
373
  end
380
374
 
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)
375
+ it "caches template views without layout when additional layout options given when given a #{template.class} with plugin option :cache=>#{cache_plugin_option}" do
376
+ app(:bare) do
377
+ plugin :render, :views=>'spec/views', :layout=>nil, :cache=>cache_plugin_option
378
+ route do
379
+ view(template)
380
+ end
400
381
  end
382
+
383
+ app.render_opts[:template_method_cache][template].must_be_nil
384
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
385
+ body.strip.must_equal "ct"
386
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
387
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
388
+ body.strip.must_equal "ct"
389
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
390
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
391
+ body.strip.must_equal "ct"
392
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
393
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
394
+ app::RodaCompiledTemplates.private_instance_methods.length.must_equal multiplier
401
395
  end
402
396
 
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
397
+ it "caches template views without layout when additional layout options given when given a #{template.class} with plugin option :cache=>#{cache_plugin_option}" do
398
+ app(:bare) do
399
+ plugin :render, :views=>'spec/views', :layout_opts=>{:locals=>{:title=>"Home"}}, :cache=>cache_plugin_option
400
+ route do
401
+ view(template)
402
+ end
403
+ end
404
+
405
+ app.render_opts[:template_method_cache][template].must_be_nil
406
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
407
+ body.strip.must_equal "<title>Roda: Home</title>\nct"
408
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
409
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
410
+ body.strip.must_equal "<title>Roda: Home</title>\nct"
411
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
412
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
413
+ body.strip.must_equal "<title>Roda: Home</title>\nct"
414
+ app.render_opts[:template_method_cache][template].must_be_kind_of(Symbol)
415
+ app.render_opts[:template_method_cache][:_roda_layout].must_be_nil
416
+ app::RodaCompiledTemplates.private_instance_methods.length.must_equal multiplier
417
+ end
415
418
  end
416
419
  end
417
420
  end
@@ -63,6 +63,38 @@ describe "type_routing plugin" do
63
63
  body('/a.html', 'HTTP_ACCEPT' => 'application/xml').must_equal 'HTML: html'
64
64
  end
65
65
 
66
+ it "works correctly in sub apps when sub app also handles extensions on empty paths" do
67
+ sup_app = app
68
+ @app = Class.new(sup_app)
69
+ sup_app.route do |r|
70
+ r.is do
71
+ r.get do
72
+ r.html { 'a' }
73
+ r.json { '{b:1}' }
74
+ end
75
+ end
76
+
77
+ r.on 'test' do
78
+ r.get do
79
+ r.html { 'c' }
80
+ r.json { '{d:2}' }
81
+ end
82
+ end
83
+ end
84
+ app.route do |r|
85
+ r.on "subpath" do
86
+ r.run(sup_app)
87
+ end
88
+ end
89
+
90
+ body('/subpath').must_equal 'a'
91
+ body('/subpath.html').must_equal 'a'
92
+ body('/subpath.json').must_equal '{b:1}'
93
+ body('/subpath/test').must_equal 'c'
94
+ body('/subpath/test.html').must_equal 'c'
95
+ body('/subpath/test.json').must_equal '{d:2}'
96
+ end
97
+
66
98
  it "uses the default if neither file extension nor Accept header are given" do
67
99
  body('/a').must_equal 'HTML: html'
68
100
  header('Content-Type', '/a').must_equal 'text/html'
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.22.0
4
+ version: 3.23.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-07-12 00:00:00.000000000 Z
11
+ date: 2019-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -219,6 +219,7 @@ extra_rdoc_files:
219
219
  - doc/release_notes/3.20.0.txt
220
220
  - doc/release_notes/3.21.0.txt
221
221
  - doc/release_notes/3.22.0.txt
222
+ - doc/release_notes/3.23.0.txt
222
223
  files:
223
224
  - CHANGELOG
224
225
  - MIT-LICENSE
@@ -277,6 +278,7 @@ files:
277
278
  - doc/release_notes/3.20.0.txt
278
279
  - doc/release_notes/3.21.0.txt
279
280
  - doc/release_notes/3.22.0.txt
281
+ - doc/release_notes/3.23.0.txt
280
282
  - doc/release_notes/3.3.0.txt
281
283
  - doc/release_notes/3.4.0.txt
282
284
  - doc/release_notes/3.5.0.txt