roda 3.20.0 → 3.21.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bce3cf55fdec3d303d3d78b6e190046b38619e9ab296b63575962864535339e5
4
- data.tar.gz: 874904308a03694809bd777c406ed94e1cefcc11bb9d7e748dd860a22c853d18
3
+ metadata.gz: 34a644ccaa69bc1913eb1f54315437ce4b215bd5925e82f720d0fda007895224
4
+ data.tar.gz: 9a85847e46720f4fa2f7a050febd5b0f6ef7db528c8fbd09836113148944f87c
5
5
  SHA512:
6
- metadata.gz: 0c08ac192ce7a3609b968404e4a3bf232ad7d12d1e70ed3e0c3306fea13ddf91bbf746bff47ec746acfc3481c5bfbaed3d7916dbf44c88c9b7f4d8855be64358
7
- data.tar.gz: c3e6e9d50efc13dcd202379a76fef8ad6305c29f38954c8ed340ce7bd274b0ffe792cecb69a8ec0ea37aebc0d9fe1aeda16ea87d50f0f8892c1d805121f635ee
6
+ metadata.gz: 739c2a26ea80aeca2bbb4b3b51c4cabf93100309956fe594b61cc66a72f6d3e2f23ab0356c81f12e4a461bf82eb1d7f9cc2d0dc5fecbef88348bd17aca17c33a
7
+ data.tar.gz: 65ef8401849ee398968ccfce12ccbf203914f7a76721c8cb0ef31b5ab9051fd7f8460361dd96abb495dfa25c5acb50141611448b7065a5be3340b8ca51cc70ff
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ = 3.21.0 (2019-06-14)
2
+
3
+ * Cache compiled templates in development mode, until the template files are modified (jeremyevans)
4
+
1
5
  = 3.20.0 (2019-05-16)
2
6
 
3
7
  * Set Content-Length header to 0 for empty 205 responses (jeremyevans)
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ VERS = lambda do
7
7
  require_relative 'lib/roda/version'
8
8
  Roda::RodaVersion
9
9
  end
10
- CLEAN.include ["#{NAME}-*.gem", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc", "spec/assets/app.*.css", "spec/assets/app.*.js", "spec/assets/app.*.css.gz", "spec/assets/app.*.js.gz"]
10
+ CLEAN.include ["#{NAME}-*.gem", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc", "spec/assets/app.*.css", "spec/assets/app.*.js", "spec/assets/app.*.css.gz", "spec/assets/app.*.js.gz", "spec/iv.erb"]
11
11
 
12
12
  # Gem Packaging and Release
13
13
 
@@ -0,0 +1,5 @@
1
+ = Improvements
2
+
3
+ * View rendering speed is significantly improved in development mode
4
+ by caching file-based templates until there has been a modification
5
+ to the template file.
@@ -48,8 +48,11 @@ class Roda
48
48
  #
49
49
  # :allowed_paths :: Set the template paths to allow. Attempts to render paths outside
50
50
  # of this directory will raise an error. Defaults to the +:views+ directory.
51
- # :cache :: nil/false to disable template caching by default. By default, caching
52
- # is disabled by default if RACK_ENV is development.
51
+ # :cache :: nil/false to explicitly disable premanent template caching. By default, permanent
52
+ # template caching is disabled by default if RACK_ENV is development. When permanent
53
+ # template caching is disabled, for templates with paths in the file system, the
54
+ # modification time of the file will be checked on every render, and if it has changed,
55
+ # a new template will be created for the current content of the file.
53
56
  # :cache_class :: A class to use as the template cache instead of the default.
54
57
  # :check_paths :: Can be set to false to turn off template path checking.
55
58
  # :engine :: The tilt engine to use for rendering, also the default file extension for
@@ -83,7 +86,7 @@ class Roda
83
86
  #
84
87
  # :cache :: Set to false to not cache this template, even when
85
88
  # caching is on by default. Set to true to force caching for
86
- # this template, even when the default is to not cache (e.g.
89
+ # this template, even when the default is to not permantently cache (e.g.
87
90
  # when using the :template_block option).
88
91
  # :cache_key :: Explicitly set the hash key to use when caching.
89
92
  # :content :: Only respected by +view+, provides the content to render
@@ -152,11 +155,11 @@ class Roda
152
155
  opts[:allowed_paths] = opts[:allowed_paths].map{|f| app.expand_path(f, nil)}.uniq.freeze
153
156
  opts[:check_paths] = true unless opts.has_key?(:check_paths)
154
157
 
155
- unless opts.has_key?(:explicit_cache)
156
- opts[:explicit_cache] = if opts.fetch(:cache, true)
157
- ENV['RACK_ENV'] == 'development'
158
- else
158
+ unless opts.has_key?(:check_template_mtime)
159
+ opts[:check_template_mtime] = if opts[:cache] == false || opts[:explicit_cache]
159
160
  true
161
+ else
162
+ ENV['RACK_ENV'] == 'development'
160
163
  end
161
164
  end
162
165
 
@@ -211,6 +214,34 @@ class Roda
211
214
  opts.freeze
212
215
  end
213
216
 
217
+ # Wrapper object for the Tilt template, that checks the modified
218
+ # time of the template file, and rebuilds the template if the
219
+ # template file has been modified.
220
+ class TemplateMtimeWrapper
221
+ def initialize(template_class, path, *template_args)
222
+ @template_class = template_class
223
+ @path = path
224
+ @template_args = template_args
225
+
226
+ @mtime = (File.mtime(path) if File.file?(path))
227
+ @template = template_class.new(path, *template_args)
228
+ end
229
+
230
+ # If the template file exists and the modification time has
231
+ # changed, rebuild the template file, then call render on it.
232
+ def render(*args, &block)
233
+ if File.file?(path = @path)
234
+ mtime = File.mtime(path)
235
+ if mtime != @mtime
236
+ @mtime = mtime
237
+ @template = @template_class.new(path, *@template_args)
238
+ end
239
+ end
240
+
241
+ @template.render(*args, &block)
242
+ end
243
+ end
244
+
214
245
  module ClassMethods
215
246
  # Copy the rendering options into the subclass, duping
216
247
  # them as necessary to prevent changes in the subclass
@@ -268,7 +299,7 @@ class Roda
268
299
  # If caching templates, attempt to retrieve the template from the cache. Otherwise, just yield
269
300
  # to get the template.
270
301
  def cached_template(opts, &block)
271
- if (!render_opts[:explicit_cache] || opts[:cache]) && (key = opts[:cache_key])
302
+ if key = opts[:cache_key]
272
303
  cache = render_opts[:cache]
273
304
  unless template = cache[key]
274
305
  template = cache[key] = yield
@@ -335,7 +366,8 @@ class Roda
335
366
 
336
367
  # Retrieve the Tilt::Template object for the given template and opts.
337
368
  def retrieve_template(opts)
338
- unless opts[:cache_key] && opts[:cache] != false
369
+ cache = opts[:cache]
370
+ if !opts[:cache_key] || cache == false
339
371
  found_template_opts = opts = find_template(opts)
340
372
  end
341
373
  cached_template(opts) do
@@ -347,7 +379,12 @@ class Roda
347
379
  if current_template_opts = opts[:template_opts]
348
380
  template_opts = template_opts.merge(current_template_opts)
349
381
  end
350
- opts[:template_class].new(opts[:path], 1, template_opts, &opts[:template_block])
382
+
383
+ if render_opts[:check_template_mtime] && !opts[:template_block] && !cache
384
+ TemplateMtimeWrapper.new(opts[:template_class], opts[:path], 1, template_opts)
385
+ else
386
+ opts[:template_class].new(opts[:path], 1, template_opts, &opts[:template_block])
387
+ end
351
388
  end
352
389
  end
353
390
 
@@ -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 = 20
7
+ RodaMinorVersion = 21
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
@@ -61,6 +61,66 @@ describe "render plugin" do
61
61
  end
62
62
  end
63
63
 
64
+ describe "render plugin" do
65
+ file = 'spec/iv.erb'
66
+ before do
67
+ File.binwrite(file, File.binread('spec/views/iv.erb'))
68
+ end
69
+ after do
70
+ File.delete(file) if File.file?(file)
71
+ end
72
+
73
+ [{:cache=>false}, {:explicit_cache=>true}, {:check_template_mtime=>true}].each do |cache_plugin_opts|
74
+ it "checks mtime if #{cache_plugin_opts} plugin option is used" do
75
+ app(:bare) do
76
+ plugin :render, {:views=>"./spec"}.merge!(cache_plugin_opts)
77
+
78
+ route do |r|
79
+ @a = 'a'
80
+ render('iv')
81
+ end
82
+ end
83
+
84
+ t = Time.now
85
+ body.strip.must_equal "a"
86
+
87
+ File.binwrite(file, File.binread(file) + "b")
88
+ File.utime(t, t+1, file)
89
+ body.gsub("\n", '').must_equal "ab"
90
+
91
+ File.binwrite(file, File.binread(file) + "c")
92
+ File.utime(t, t+2, file)
93
+ body.gsub("\n", '').must_equal "abc"
94
+
95
+ mtime = File.mtime(file)
96
+ File.binwrite(file, File.binread(file) + "d")
97
+ File.utime(t, mtime, file)
98
+ body.gsub("\n", '').must_equal "abc"
99
+
100
+ File.delete(file)
101
+ body.gsub("\n", '').must_equal "abc"
102
+ end
103
+ end
104
+
105
+ it "does not check mtime if :cache render option is used" do
106
+ app(:bare) do
107
+ plugin :render, :views=>"./spec", :cache=>false
108
+
109
+ route do |r|
110
+ @a = 'a'
111
+ render('iv', :cache=>true)
112
+ end
113
+ end
114
+
115
+ t = Time.now+1
116
+ body.strip.must_equal "a"
117
+
118
+ File.binwrite(file, File.binread(file) + "b")
119
+ File.utime(t, t+1, file)
120
+ body.gsub("\n", '').must_equal "a"
121
+ end
122
+ end
123
+
64
124
  describe "render plugin" do
65
125
  it "simple layout support" do
66
126
  app(:bare) do
@@ -322,13 +382,13 @@ describe "render plugin" do
322
382
  body('/c').must_equal "3"
323
383
  end
324
384
 
325
- it "Default to :explicit_cache=>true in development mode" do
385
+ it "Default to :check_template_mtime=>true in development mode" do
326
386
  with_rack_env('development') do
327
387
  app(:render){}
328
388
  end
329
- app.render_opts[:explicit_cache].must_equal true
389
+ app.render_opts[:check_template_mtime].must_equal true
330
390
  app(:render){}
331
- app.render_opts[:explicit_cache].must_equal false
391
+ app.render_opts[:check_template_mtime].must_equal false
332
392
  end
333
393
 
334
394
  it "Support :cache=>false plugin option to disable template caching by default, except :cache=>true method option is given" do
@@ -365,7 +425,7 @@ describe "render plugin" do
365
425
  body('/a').strip.must_equal "a"
366
426
  app.render_opts[:cache][File.expand_path('spec/views/iv.erb')].must_be_nil
367
427
  body('/b').strip.must_equal "a"
368
- app.render_opts[:cache][File.expand_path('spec/views/iv.erb')].wont_equal nil
428
+ app.render_opts[:cache][File.expand_path('spec/views/iv.erb')].wont_be_nil
369
429
  end
370
430
 
371
431
  it "Support :cache=>false option to disable template caching even when :cache_key is given" do
@@ -382,41 +442,28 @@ describe "render plugin" do
382
442
  body('/a').strip.must_equal "a"
383
443
  app.render_opts[:cache][:foo].must_be_nil
384
444
  body('/b').strip.must_equal "a"
385
- app.render_opts[:cache][:foo].wont_equal nil
445
+ app.render_opts[:cache][:foo].wont_be_nil
386
446
  end
387
447
 
388
- it "Support :explicit_cache option to disable caching by default, but still allow caching on a per-call basis" do
389
- app(:bare) do
390
- plugin :render, :views=>"./spec/views", :explicit_cache=>true
391
-
392
- route do |r|
393
- @a = 'a'
394
- r.is('a'){render('iv')}
395
- render('iv', :cache=>true)
396
- end
397
- end
398
-
399
- body('/a').strip.must_equal "a"
400
- app.render_opts[:cache][File.expand_path('spec/views/iv.erb')].must_be_nil
401
- body('/b').strip.must_equal "a"
402
- app.render_opts[:cache][File.expand_path('spec/views/iv.erb')].wont_equal nil
403
- end
448
+ [{}, {:cache=>true}].each do |cache_val_opts|
449
+ [{}, {:cache_key=>:foo}].each do |cache_key_opts|
450
+ cache_opts = cache_key_opts.merge(cache_val_opts)
451
+ it "Support :explicit_cache plugin option with #{cache_opts} render option" do
452
+ app(:bare) do
453
+ plugin :render, :views=>"./spec/views", :explicit_cache=>true
404
454
 
405
- it "Support :explicit_cache plugin option with :cache_key render option" do
406
- app(:bare) do
407
- plugin :render, :views=>"./spec/views", :explicit_cache=>true
455
+ route do |r|
456
+ @a = 'a'
457
+ render('iv', cache_opts)
458
+ end
459
+ end
408
460
 
409
- route do |r|
410
- @a = 'a'
411
- r.is('a'){render('iv', :cache_key=>:foo)}
412
- render('iv', :cache=>true, :cache_key=>:foo)
461
+ body('/a').strip.must_equal "a"
462
+ template = app.render_opts[:cache][cache_opts[:cache_key] || File.expand_path("spec/views/iv.erb")]
463
+ template.must_be_kind_of(cache_val_opts.empty? ? Roda::RodaPlugins::Render::TemplateMtimeWrapper : Tilt::Template)
464
+ body('/a').strip.must_equal "a"
413
465
  end
414
466
  end
415
-
416
- body('/a').strip.must_equal "a"
417
- app.render_opts[:cache][:foo].must_be_nil
418
- body('/b').strip.must_equal "a"
419
- app.render_opts[:cache][:foo].wont_equal nil
420
467
  end
421
468
 
422
469
  it "Support :cache=>true option to enable template caching when :template_block is used" do
@@ -445,7 +492,7 @@ describe "render plugin" do
445
492
  body('/a').strip.must_equal "iv-a"
446
493
  app.render_opts[:cache][['iv', c, nil, nil, proca]].must_be_nil
447
494
  body('/b').strip.must_equal "iv-a"
448
- app.render_opts[:cache][['iv', c, nil, nil, proca]].wont_equal nil
495
+ app.render_opts[:cache][['iv', c, nil, nil, proca]].wont_be_nil
449
496
  end
450
497
 
451
498
  it "Support :cache_key option to force the key used when caching, unless :cache=>false option is used" do
@@ -500,17 +547,17 @@ describe "render plugin" do
500
547
  c = Class.new(Roda)
501
548
  c.plugin :render
502
549
  cache = c.render_opts[:cache]
503
- c.render_opts[:explicit_cache].must_equal false
550
+ c.render_opts[:check_template_mtime].must_equal false
504
551
  c.plugin :render
505
552
  c.render_opts[:cache].must_be_same_as cache
506
- c.render_opts[:explicit_cache].must_equal false
553
+ c.render_opts[:check_template_mtime].must_equal false
507
554
 
508
555
  c.plugin :render, :cache=>false
509
556
  c.render_opts[:cache].must_be_same_as cache
510
- c.render_opts[:explicit_cache].must_equal true
557
+ c.render_opts[:check_template_mtime].must_equal true
511
558
  c.plugin :render
512
559
  c.render_opts[:cache].must_be_same_as cache
513
- c.render_opts[:explicit_cache].must_equal true
560
+ c.render_opts[:check_template_mtime].must_equal true
514
561
  end
515
562
 
516
563
  it "render plugin call should not override existing options" do
@@ -530,7 +577,7 @@ describe "render plugin" do
530
577
  end
531
578
 
532
579
  body("/inline").strip.must_equal "Hello Agent Smith"
533
- Class.new(app).render_opts[:cache][:a].must_be_nil
580
+ Class.new(app).render_opts[:check_template_mtime].must_equal true
534
581
  end
535
582
 
536
583
  it "with :check_paths=>true plugin option used" do
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.20.0
4
+ version: 3.21.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-05-16 00:00:00.000000000 Z
11
+ date: 2019-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -217,6 +217,7 @@ extra_rdoc_files:
217
217
  - doc/release_notes/3.18.0.txt
218
218
  - doc/release_notes/3.19.0.txt
219
219
  - doc/release_notes/3.20.0.txt
220
+ - doc/release_notes/3.21.0.txt
220
221
  files:
221
222
  - CHANGELOG
222
223
  - MIT-LICENSE
@@ -273,6 +274,7 @@ files:
273
274
  - doc/release_notes/3.19.0.txt
274
275
  - doc/release_notes/3.2.0.txt
275
276
  - doc/release_notes/3.20.0.txt
277
+ - doc/release_notes/3.21.0.txt
276
278
  - doc/release_notes/3.3.0.txt
277
279
  - doc/release_notes/3.4.0.txt
278
280
  - doc/release_notes/3.5.0.txt