roda 3.39.0 → 3.40.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: 4f01105e24f4eae80a69f5734f93d3dfe54b5f6be2489521f1d886053c569102
4
- data.tar.gz: 2aebf30460c7d5352ee15baf3f884e59dac972e0aadd63aa7ab81445a8a29f65
3
+ metadata.gz: 8e87645db18482f3ad97d106e268d76b2567d074490f37d7e99d52d06e4e5483
4
+ data.tar.gz: b84b082c2f27fcbd31254cb80de5e6610b7417e722eaf3dc3d8753a4604a0701
5
5
  SHA512:
6
- metadata.gz: d3fd374b3d700106ca814fff8f2dd0c66a3295955f27a453ef5d9fb2ba7fdea583d76ce82f91efb8e2ebcbb97a07e664f3f008689d51eb67ae39aebdd86a5d0e
7
- data.tar.gz: 59c34c88ab1e5a5bc5017d46707a530c7cd002f4262c30751ba6429983b32477b813d83ada45a19873be711d1d2bd0abd95fe2a5c44c01038ad4a32dbb8f276d
6
+ metadata.gz: 3b21d6fa4b33c029a8b23a8ec437e70e2799e3f2bec27239d3cbfc5a1a4bb8cd82fc95309ad27d22243695298535b02687b0948218df1f7a1a0812242079e3b7
7
+ data.tar.gz: 3dc9629b16a4d9f496cee61bc40396f6893bfe114666ba7554327cd052946719410e2f4e89a27388cea291fd7b5ba1bcd37c669aa1dfc7b64c48a6622bafb013
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ = 3.40.0 (2021-01-14)
2
+
3
+ * Add freeze_template_caches! to the precompile_templates plugin, which ensures all templates are precompiled, and speeds up template access (jeremyevans)
4
+
5
+ * Add precompile_views to the precompile_templates plugin, which precompiles the optimized render methods (jeremyevans)
6
+
7
+ * Have RodaCache#freeze return the frozen internal hash (which no longer needs a mutex for thread-safety) (jeremyevans)
8
+
9
+ * Speed up the view method in the render plugin even more when freezing the application (jeremyevans)
10
+
11
+ * Speed up the view method in the render plugin when called with a single argument (jeremyevans)
12
+
1
13
  = 3.39.0 (2020-12-15)
2
14
 
3
15
  * Speed up relative_path plugin if relative_path or relative_prefix is called more than once (jeremyevans)
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2020 Jeremy Evans
1
+ Copyright (c) 2014-2021 Jeremy Evans
2
2
  Copyright (c) 2010-2014 Michel Martens, Damian Janowski and Cyril David
3
3
  Copyright (c) 2008-2009 Christian Neukirchen
4
4
 
@@ -0,0 +1,24 @@
1
+ = New Features
2
+
3
+ * A precompile_views method has been added to the
4
+ precompile_templates plugin. This method works with Roda's
5
+ optimized compiled view methods, allowing additional memory
6
+ sharing between parent and child processes.
7
+
8
+ * A freeze_template_caches! method has been added to the
9
+ precompile_templates plugin. This freezes the template caches,
10
+ preventing the compilation of additional templates, useful for
11
+ enforcing that only precompiled templates are used. Additionally,
12
+ this speeds up access to the template caches.
13
+
14
+ * RodaCache#freeze now returns the frozen internal hash, which can
15
+ then be accessed without a mutex. Previously, freeze only froze
16
+ the receiver and not the internal hash, so it didn't have the
17
+ expected effect.
18
+
19
+ = Other Improvements
20
+
21
+ * The view method in the render plugin is now faster in most cases
22
+ when a single argument is used. When freezing the application,
23
+ an additional optimization is performed to increase the
24
+ performance of the view method even further.
@@ -22,6 +22,13 @@ class Roda
22
22
  @mutex.synchronize{@hash[key] = value}
23
23
  end
24
24
 
25
+ # Return the frozen internal hash. The internal hash can then
26
+ # be accessed directly since it is frozen and there are no
27
+ # thread safety issues.
28
+ def freeze
29
+ @hash.freeze
30
+ end
31
+
25
32
  private
26
33
 
27
34
  # Create a copy of the cache with a separate mutex.
@@ -13,32 +13,33 @@ class Roda
13
13
  # all of the child processes can use the same precompiled templates, which
14
14
  # saves memory.
15
15
  #
16
- # After loading the plugin, you can call +precompile_templates+ with
17
- # the pattern of templates you would like to precompile:
16
+ # Another advantage of the precompile_templates plugin is that after
17
+ # template precompilation, access to the template file in the file system is
18
+ # no longer needed, so this can be used with security features that do not
19
+ # allow access to the template files at runtime.
20
+ #
21
+ # After loading the plugin, you should call precompile_views with an array
22
+ # of views to compile, using the same argument you are passing to view or
23
+ # render:
18
24
  #
19
25
  # plugin :precompile_templates
20
- # precompile_templates "views/\*\*/*.erb"
26
+ # precompile_views %w'view1 view2'
27
+ #
28
+ # If the view requires local variables, you should call precompile_views with a second
29
+ # argument for the local variables:
21
30
  #
22
- # That will precompile all erb template files in the views directory or
23
- # any subdirectory.
31
+ # plugin :precompile_templates
32
+ # precompile_views :view3, [:local_var1, :local_var2]
24
33
  #
25
- # If the templates use local variables, you need to specify which local
26
- # variables to precompile, which should be an array of symbols:
34
+ # After all templates are precompiled, you can optionally use freeze_template_caches!,
35
+ # which will freeze the template caches so that any template compilation at runtime
36
+ # will result in an error. This also speeds up template cache access, since the
37
+ # template caches no longer need a mutex.
27
38
  #
28
- # precompile_templates 'views/users/_*.erb', locals: [:user]
39
+ # freeze_template_caches!
29
40
  #
30
41
  # Note that you should use Tilt 2.0.1+ if you are using this plugin, so
31
42
  # that locals are handled in the same order.
32
- #
33
- # You can specify other render options when calling +precompile_templates+,
34
- # including +:cache_key+, +:template_class+, and +:template_opts+. If you
35
- # are passing any of those options to render/view for the template, you
36
- # should pass the same options when precompiling the template.
37
- #
38
- # To compile inline templates, just pass a single hash containing an :inline
39
- # to +precompile_templates+:
40
- #
41
- # precompile_templates inline: some_template_string
42
43
  module PrecompileTemplates
43
44
  # Load the render plugin as precompile_templates depends on it.
44
45
  def self.load_dependencies(app, opts=OPTS)
@@ -46,8 +47,49 @@ class Roda
46
47
  end
47
48
 
48
49
  module ClassMethods
49
- # Precompile the templates using the given options. See PrecompileTemplates
50
- # for details.
50
+ # Freeze the template caches. Should be called after precompiling all templates during
51
+ # application startup, if you don't want to allow templates to be cached at runtime.
52
+ # In addition to ensuring that no templates are compiled at runtime, this also speeds
53
+ # up rendering by freezing the template caches, so that a mutex is not needed to access
54
+ # them.
55
+ def freeze_template_caches!
56
+ _freeze_layout_method
57
+
58
+ opts[:render] = render_opts.merge(
59
+ :cache=>render_opts[:cache].freeze,
60
+ :template_method_cache=>render_opts[:template_method_cache].freeze,
61
+ ).freeze
62
+ self::RodaCompiledTemplates.freeze
63
+
64
+ nil
65
+ end
66
+
67
+ # Precompile the templates using the given options. Note that this doesn't
68
+ # handle optimized template methods supported in newer versions of Roda, but
69
+ # there are still cases where makes sense to use it.
70
+ #
71
+ # You can call +precompile_templates+ with the pattern of templates you would
72
+ # like to precompile:
73
+ #
74
+ # precompile_templates "views/**/*.erb"
75
+ #
76
+ # That will precompile all erb template files in the views directory or
77
+ # any subdirectory.
78
+ #
79
+ # If the templates use local variables, you need to specify which local
80
+ # variables to precompile, which should be an array of symbols:
81
+ #
82
+ # precompile_templates 'views/users/_*.erb', locals: [:user]
83
+ #
84
+ # You can specify other render options when calling +precompile_templates+,
85
+ # including +:cache_key+, +:template_class+, and +:template_opts+. If you
86
+ # are passing any of those options to render/view for the template, you
87
+ # should pass the same options when precompiling the template.
88
+ #
89
+ # To compile inline templates, just pass a single hash containing an :inline
90
+ # to +precompile_templates+:
91
+ #
92
+ # precompile_templates inline: some_template_string
51
93
  def precompile_templates(pattern, opts=OPTS)
52
94
  if pattern.is_a?(Hash)
53
95
  opts = pattern.merge(opts)
@@ -68,7 +110,40 @@ class Roda
68
110
  instance = allocate
69
111
  compile_opts.each do |compile_opt|
70
112
  template = instance.send(:retrieve_template, compile_opt)
71
- Render.tilt_template_compiled_method(template, locals, self)
113
+ begin
114
+ Render.tilt_template_compiled_method(template, locals, self)
115
+ rescue NotImplementedError
116
+ # When freezing template caches, you may want to precompile a template for a
117
+ # template type that doesn't support template precompilation, just to populate
118
+ # the cache. Tilt rescues NotImplementedError in this case, which we can ignore.
119
+ nil
120
+ end
121
+ end
122
+
123
+ nil
124
+ end
125
+
126
+ # Precompile the given views with the given locals, handling optimized template methods.
127
+ def precompile_views(views, locals=EMPTY_ARRAY)
128
+ instance = allocate
129
+ views = Array(views)
130
+
131
+ if locals.empty?
132
+ opts = OPTS
133
+ else
134
+ locals_hash = {}
135
+ locals.each{|k| locals_hash[k] = nil}
136
+ opts = {:locals=>locals_hash}
137
+ end
138
+
139
+ views.each do |view|
140
+ instance.send(:retrieve_template, instance.send(:render_template_opts, view, opts))
141
+ end
142
+
143
+ if locals_hash
144
+ views.each do |view|
145
+ instance.send(:_optimized_render_method_for_locals, view, locals_hash)
146
+ end
72
147
  end
73
148
 
74
149
  nil
@@ -333,6 +333,25 @@ class Roda
333
333
  end
334
334
 
335
335
  module ClassMethods
336
+ # :nocov:
337
+ if COMPILED_METHOD_SUPPORT
338
+ # :nocov:
339
+ # If using compiled methods and there is an optimized layout, speed up
340
+ # access to the layout method to improve the performance of view.
341
+ def freeze
342
+ begin
343
+ _freeze_layout_method
344
+ rescue
345
+ # This is only for optimization, if any errors occur, they can be ignored.
346
+ # One possibility for error is the app doesn't use a layout, but doesn't
347
+ # specifically set the :layout=>false plugin option.
348
+ nil
349
+ end
350
+
351
+ super
352
+ end
353
+ end
354
+
336
355
  # Copy the rendering options into the subclass, duping
337
356
  # them as necessary to prevent changes in the subclass
338
357
  # affecting the parent class.
@@ -352,6 +371,27 @@ class Roda
352
371
  def render_opts
353
372
  opts[:render]
354
373
  end
374
+
375
+ private
376
+
377
+ # Precompile the layout method, to reduce method calls to look it up at runtime.
378
+ def _freeze_layout_method
379
+ if render_opts[:layout]
380
+ instance = allocate
381
+ instance.send(:retrieve_template, instance.send(:view_layout_opts, OPTS))
382
+
383
+ # :nocov:
384
+ if COMPILED_METHOD_SUPPORT
385
+ # :nocov:
386
+ if (layout_template = render_opts[:optimize_layout]) && !opts[:render][:optimized_layout_method_created]
387
+ instance.send(:retrieve_template, :template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
388
+ layout_method = opts[:render][:template_method_cache][:_roda_layout]
389
+ define_method(:_layout_method){layout_method}
390
+ opts[:render] = opts[:render].merge(:optimized_layout_method_created=>true)
391
+ end
392
+ end
393
+ end
394
+ end
355
395
  end
356
396
 
357
397
  module InstanceMethods
@@ -379,15 +419,19 @@ class Roda
379
419
  if optimized_template
380
420
  content = send(optimized_template, OPTS)
381
421
 
382
- render_opts = self.class.opts[:render]
383
- if layout_template = render_opts[:optimize_layout]
384
- method_cache = render_opts[:template_method_cache]
385
- unless layout_method = method_cache[:_roda_layout]
386
- retrieve_template(:template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
387
- layout_method = method_cache[:_roda_layout]
388
- end
422
+ # First, check if the optimized layout method has already been created,
423
+ # and use it if so. This way avoids the extra conditional and local variable
424
+ # assignments in the next section.
425
+ if layout_method = _layout_method
426
+ return send(layout_method, OPTS){content}
427
+ end
389
428
 
390
- if layout_method
429
+ # If we have an optimized template method but no optimized layout method, create the
430
+ # optimized layout method if possible and use it. If you can't create the optimized
431
+ # layout method, fall through to the slower approach.
432
+ if layout_template = self.class.opts[:render][:optimize_layout]
433
+ retrieve_template(:template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
434
+ if layout_method = _layout_method
391
435
  return send(layout_method, OPTS){content}
392
436
  end
393
437
  end
@@ -428,6 +472,11 @@ class Roda
428
472
  method_cache[template]
429
473
  end
430
474
 
475
+ # Return a symbol containing the optimized layout method
476
+ def _layout_method
477
+ self.class.opts[:render][:template_method_cache][:_roda_layout]
478
+ end
479
+
431
480
  # Use an optimized render path for templates with a hash of locals. Returns the result
432
481
  # of the template render if the optimized path is used, or nil if the optimized
433
482
  # path is not used and the long method needs to be used.
@@ -471,11 +520,15 @@ class Roda
471
520
  end
472
521
  else
473
522
  # :nocov:
474
- def _cached_template_method(template)
523
+ def _cached_template_method(_)
475
524
  nil
476
525
  end
477
526
 
478
- def _cached_template_method_key(template)
527
+ def _cached_template_method_key(_)
528
+ nil
529
+ end
530
+
531
+ def _layout_method
479
532
  nil
480
533
  end
481
534
 
@@ -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 = 39
7
+ RodaMinorVersion = 40
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
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.39.0
4
+ version: 3.40.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: 2020-12-15 00:00:00.000000000 Z
11
+ date: 2021-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -174,16 +174,8 @@ extra_rdoc_files:
174
174
  - MIT-LICENSE
175
175
  - CHANGELOG
176
176
  - doc/conventions.rdoc
177
- - doc/release_notes/3.7.0.txt
178
177
  - doc/release_notes/3.0.0.txt
179
178
  - doc/release_notes/3.1.0.txt
180
- - doc/release_notes/3.2.0.txt
181
- - doc/release_notes/3.3.0.txt
182
- - doc/release_notes/3.4.0.txt
183
- - doc/release_notes/3.5.0.txt
184
- - doc/release_notes/3.6.0.txt
185
- - doc/release_notes/3.8.0.txt
186
- - doc/release_notes/3.9.0.txt
187
179
  - doc/release_notes/3.10.0.txt
188
180
  - doc/release_notes/3.11.0.txt
189
181
  - doc/release_notes/3.12.0.txt
@@ -195,6 +187,7 @@ extra_rdoc_files:
195
187
  - doc/release_notes/3.17.0.txt
196
188
  - doc/release_notes/3.18.0.txt
197
189
  - doc/release_notes/3.19.0.txt
190
+ - doc/release_notes/3.2.0.txt
198
191
  - doc/release_notes/3.20.0.txt
199
192
  - doc/release_notes/3.21.0.txt
200
193
  - doc/release_notes/3.22.0.txt
@@ -205,6 +198,7 @@ extra_rdoc_files:
205
198
  - doc/release_notes/3.27.0.txt
206
199
  - doc/release_notes/3.28.0.txt
207
200
  - doc/release_notes/3.29.0.txt
201
+ - doc/release_notes/3.3.0.txt
208
202
  - doc/release_notes/3.30.0.txt
209
203
  - doc/release_notes/3.31.0.txt
210
204
  - doc/release_notes/3.32.0.txt
@@ -215,6 +209,13 @@ extra_rdoc_files:
215
209
  - doc/release_notes/3.37.0.txt
216
210
  - doc/release_notes/3.38.0.txt
217
211
  - doc/release_notes/3.39.0.txt
212
+ - doc/release_notes/3.4.0.txt
213
+ - doc/release_notes/3.40.0.txt
214
+ - doc/release_notes/3.5.0.txt
215
+ - doc/release_notes/3.6.0.txt
216
+ - doc/release_notes/3.7.0.txt
217
+ - doc/release_notes/3.8.0.txt
218
+ - doc/release_notes/3.9.0.txt
218
219
  files:
219
220
  - CHANGELOG
220
221
  - MIT-LICENSE
@@ -256,6 +257,7 @@ files:
256
257
  - doc/release_notes/3.38.0.txt
257
258
  - doc/release_notes/3.39.0.txt
258
259
  - doc/release_notes/3.4.0.txt
260
+ - doc/release_notes/3.40.0.txt
259
261
  - doc/release_notes/3.5.0.txt
260
262
  - doc/release_notes/3.6.0.txt
261
263
  - doc/release_notes/3.7.0.txt
@@ -394,7 +396,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
394
396
  - !ruby/object:Gem::Version
395
397
  version: '0'
396
398
  requirements: []
397
- rubygems_version: 3.1.4
399
+ rubygems_version: 3.2.3
398
400
  signing_key:
399
401
  specification_version: 4
400
402
  summary: Routing tree web toolkit