roda 3.41.0 → 3.42.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 +12 -0
- data/doc/release_notes/3.42.0.txt +21 -0
- data/lib/roda.rb +6 -0
- data/lib/roda/plugins/assets.rb +31 -10
- data/lib/roda/plugins/common_logger.rb +3 -2
- data/lib/roda/plugins/custom_matchers.rb +2 -0
- data/lib/roda/plugins/recheck_precompiled_assets.rb +107 -0
- data/lib/roda/plugins/render.rb +2 -0
- data/lib/roda/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e2bdd27a69c76000c9c1d2d8f37f9919145fdae55224706c78adec42850c5d21
|
|
4
|
+
data.tar.gz: 8b92e1dbc9ec83ebca5d2d5b068c67fa282dfee25fe241451c93228a406a4749
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c9f2d3f0f021b7b0a16628cefe28c4d4001f2a80804f2bde9b48b641a70482a5d13d699252cb9f7c747de50710b91df30f893f83263e3e73c874621948b4cc6
|
|
7
|
+
data.tar.gz: c060f123bfb7bd0f02a83d864169d7d2a021c14cd152b8f3e7641c4c7e0317affb84fce0812afcb0d382e0828e31e2fd97b46482338ae92574fbad97793c8996
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
= 3.42.0 (2021-03-12)
|
|
2
|
+
|
|
3
|
+
* Make Roda.plugin support plugins using keyword arguments in Ruby 3 (jeremyevans)
|
|
4
|
+
|
|
5
|
+
* Make Roda.use support middleware using keyword arguments in Ruby 3 (pat) (#207)
|
|
6
|
+
|
|
7
|
+
* Support common_logger plugin :method option for specifying the method to call on the logger (fnordfish, jeremyevans) (#206)
|
|
8
|
+
|
|
9
|
+
* Add recheck_precompiled_assets plugin for checking for updates to the precompiled asset metadata file (jeremyevans)
|
|
10
|
+
|
|
11
|
+
* Make compile_assets class method in assets plugin use an atomic approach to writing precompiled metadata file (jeremyevans)
|
|
12
|
+
|
|
1
13
|
= 3.41.0 (2021-02-17)
|
|
2
14
|
|
|
3
15
|
* Improve view performance with :content option up to 3x by calling compiled template methods directly (jeremyevans)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
= New Features
|
|
2
|
+
|
|
3
|
+
* A recheck_precompiled_assets plugin has been added, which allows
|
|
4
|
+
for checking for updates to the precompiled asset metadata file,
|
|
5
|
+
and automatically using the updated data.
|
|
6
|
+
|
|
7
|
+
* The common_logger plugin now supports a :method plugin option to
|
|
8
|
+
specify the method to call on the logger.
|
|
9
|
+
|
|
10
|
+
= Other Improvements
|
|
11
|
+
|
|
12
|
+
* Plugins and middleware that use keyword arguments are now supported
|
|
13
|
+
in Ruby 3.
|
|
14
|
+
|
|
15
|
+
* The compile_assets class method in the assets plugin now uses an
|
|
16
|
+
atomic approach to writing the precompiled asset metadata file.
|
|
17
|
+
|
|
18
|
+
* Minor method visibility issues have been fixed. The custom_matchers
|
|
19
|
+
plugin no longer makes the unsupported_matcher request method
|
|
20
|
+
public, and the render plugin no longer makes the _layout_method
|
|
21
|
+
public when the application is frozen.
|
data/lib/roda.rb
CHANGED
|
@@ -292,6 +292,9 @@ class Roda
|
|
|
292
292
|
plugin.configure(self, *args, &block) if plugin.respond_to?(:configure)
|
|
293
293
|
@app = nil
|
|
294
294
|
end
|
|
295
|
+
# :nocov:
|
|
296
|
+
ruby2_keywords(:plugin) if respond_to?(:ruby2_keywords, true)
|
|
297
|
+
# :nocov:
|
|
295
298
|
|
|
296
299
|
# Setup routing tree for the current Roda application, and build the
|
|
297
300
|
# underlying rack application using the stored middleware. Requires
|
|
@@ -327,6 +330,9 @@ class Roda
|
|
|
327
330
|
@middleware << [args, block].freeze
|
|
328
331
|
@app = nil
|
|
329
332
|
end
|
|
333
|
+
# :nocov:
|
|
334
|
+
ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
|
|
335
|
+
# :nocov:
|
|
330
336
|
|
|
331
337
|
private
|
|
332
338
|
|
data/lib/roda/plugins/assets.rb
CHANGED
|
@@ -376,7 +376,7 @@ class Roda
|
|
|
376
376
|
|
|
377
377
|
if opts[:precompiled] && !opts[:compiled] && ::File.exist?(opts[:precompiled])
|
|
378
378
|
require 'json'
|
|
379
|
-
opts[:compiled] =
|
|
379
|
+
opts[:compiled] = app.send(:_precompiled_asset_metadata, opts[:precompiled])
|
|
380
380
|
end
|
|
381
381
|
|
|
382
382
|
if opts[:early_hints]
|
|
@@ -455,7 +455,7 @@ class Roda
|
|
|
455
455
|
require 'fileutils'
|
|
456
456
|
|
|
457
457
|
unless assets_opts[:compiled]
|
|
458
|
-
opts[:assets] = assets_opts.merge(:compiled =>
|
|
458
|
+
opts[:assets] = assets_opts.merge(:compiled => _compiled_assets_initial_hash).freeze
|
|
459
459
|
end
|
|
460
460
|
|
|
461
461
|
if type == nil
|
|
@@ -465,10 +465,12 @@ class Roda
|
|
|
465
465
|
_compile_assets(type)
|
|
466
466
|
end
|
|
467
467
|
|
|
468
|
-
if assets_opts[:precompiled]
|
|
468
|
+
if precompile_file = assets_opts[:precompiled]
|
|
469
469
|
require 'json'
|
|
470
|
-
::FileUtils.mkdir_p(File.dirname(
|
|
471
|
-
|
|
470
|
+
::FileUtils.mkdir_p(File.dirname(precompile_file))
|
|
471
|
+
tmp_file = "#{precompile_file}.tmp"
|
|
472
|
+
::File.open(tmp_file, 'wb'){|f| f.write((opts[:json_serializer] || :to_json.to_proc).call(assets_opts[:compiled]))}
|
|
473
|
+
::File.rename(tmp_file, precompile_file)
|
|
472
474
|
end
|
|
473
475
|
|
|
474
476
|
assets_opts[:compiled]
|
|
@@ -476,6 +478,11 @@ class Roda
|
|
|
476
478
|
|
|
477
479
|
private
|
|
478
480
|
|
|
481
|
+
# The initial hash to use to store compiled asset metadata.
|
|
482
|
+
def _compiled_assets_initial_hash
|
|
483
|
+
{}
|
|
484
|
+
end
|
|
485
|
+
|
|
479
486
|
# Internals of compile_assets, handling recursive calls for loading
|
|
480
487
|
# all asset groups under the given type.
|
|
481
488
|
def _compile_assets(type)
|
|
@@ -493,6 +500,11 @@ class Roda
|
|
|
493
500
|
end
|
|
494
501
|
end
|
|
495
502
|
|
|
503
|
+
# The precompiled asset metadata stored in the given file
|
|
504
|
+
def _precompiled_asset_metadata(file)
|
|
505
|
+
(opts[:json_parser] || ::JSON.method(:parse)).call(::File.read(file))
|
|
506
|
+
end
|
|
507
|
+
|
|
496
508
|
# Compile each array of files for the given type into a single
|
|
497
509
|
# file. Dirs should be an array of asset group names, if these
|
|
498
510
|
# are files in an asset group.
|
|
@@ -794,23 +806,32 @@ class Roda
|
|
|
794
806
|
# handled.
|
|
795
807
|
def assets_matchers
|
|
796
808
|
@assets_matchers ||= [:css, :js].map do |t|
|
|
797
|
-
|
|
809
|
+
if regexp = assets_regexp(t)
|
|
810
|
+
[t, regexp].freeze
|
|
811
|
+
end
|
|
798
812
|
end.compact.freeze
|
|
799
813
|
end
|
|
800
814
|
|
|
801
815
|
private
|
|
802
816
|
|
|
817
|
+
# A string for the asset filename for the asset type, key, and digest.
|
|
818
|
+
def _asset_regexp(type, key, digest)
|
|
819
|
+
"#{key.sub(/\A#{type}/, '')}.#{digest}.#{type}"
|
|
820
|
+
end
|
|
821
|
+
|
|
803
822
|
# The regexp matcher to use for the given type. This handles any asset groups
|
|
804
823
|
# for the asset types.
|
|
805
824
|
def assets_regexp(type)
|
|
806
825
|
o = roda_class.assets_opts
|
|
807
826
|
if compiled = o[:compiled]
|
|
808
|
-
assets = compiled.
|
|
809
|
-
|
|
810
|
-
|
|
827
|
+
assets = compiled.
|
|
828
|
+
select{|k,_| k =~ /\A#{type}/}.
|
|
829
|
+
map{|k, md| _asset_regexp(type, k, md)}
|
|
830
|
+
return if assets.empty?
|
|
811
831
|
/#{o[:"compiled_#{type}_prefix"]}(#{Regexp.union(assets)})/
|
|
812
832
|
else
|
|
813
|
-
assets =
|
|
833
|
+
return unless assets = o[type]
|
|
834
|
+
assets = unnest_assets_hash(assets)
|
|
814
835
|
ts = o[:timestamp_paths]
|
|
815
836
|
/#{o[:"#{type}_prefix"]}#{"\\d+#{ts}" if ts}(#{Regexp.union(assets.uniq)})#{o[:"#{type}_suffix"]}/
|
|
816
837
|
end
|
|
@@ -18,10 +18,11 @@ class Roda
|
|
|
18
18
|
# plugin :common_logger
|
|
19
19
|
# plugin :common_logger, $stdout
|
|
20
20
|
# plugin :common_logger, Logger.new('filename')
|
|
21
|
+
# plugin :common_logger, Logger.new('filename'), method: :debug
|
|
21
22
|
module CommonLogger
|
|
22
|
-
def self.configure(app, logger=nil)
|
|
23
|
+
def self.configure(app, logger=nil, opts=OPTS)
|
|
23
24
|
app.opts[:common_logger] = logger || app.opts[:common_logger] || $stderr
|
|
24
|
-
app.opts[:common_logger_meth] = app.opts[:common_logger].method(logger.respond_to?(:write) ? :write : :<<)
|
|
25
|
+
app.opts[:common_logger_meth] = app.opts[:common_logger].method(opts.fetch(:method){logger.respond_to?(:write) ? :write : :<<})
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
if RUBY_VERSION >= '2.1'
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class Roda
|
|
5
|
+
module RodaPlugins
|
|
6
|
+
# The recheck_precompiled_assets plugin enables checking for the precompiled asset metadata file.
|
|
7
|
+
# You need to have already loaded the assets plugin with the +:precompiled+ option and the file
|
|
8
|
+
# specified by the +:precompiled+ option must already exist in order to use the
|
|
9
|
+
# recheck_precompiled_assets plugin.
|
|
10
|
+
#
|
|
11
|
+
# Any time you want to check whether the precompiled asset metadata file has changed and should be
|
|
12
|
+
# reloaded, you can call the +recheck_precompiled_assets+ class method. This method will check
|
|
13
|
+
# whether the file has changed, and reload it if it has. If you want to check for modifications on
|
|
14
|
+
# every request, you can use +self.class.recheck_precompiled_assets+ inside your route block.
|
|
15
|
+
module RecheckPrecompiledAssets
|
|
16
|
+
# Thread safe wrapper for the compiled asset metadata hash. Does not wrap all
|
|
17
|
+
# hash methods, only a few that are used.
|
|
18
|
+
class CompiledAssetsHash
|
|
19
|
+
include Enumerable
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@hash = {}
|
|
23
|
+
@mutex = Mutex.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def [](key)
|
|
27
|
+
@mutex.synchronize{@hash[key]}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def []=(key, value)
|
|
31
|
+
@mutex.synchronize{@hash[key] = value}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def replace(hash)
|
|
35
|
+
hash = hash.instance_variable_get(:@hash) if (CompiledAssetsHash === hash)
|
|
36
|
+
@mutex.synchronize{@hash.replace(hash)}
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def each(&block)
|
|
41
|
+
@mutex.synchronize{@hash.dup}.each(&block)
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def to_json(*args)
|
|
46
|
+
@mutex.synchronize{@hash.dup}.to_json(*args)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.load_dependencies(app)
|
|
51
|
+
unless app.respond_to?(:assets_opts) && app.assets_opts[:precompiled]
|
|
52
|
+
raise RodaError, "must load assets plugin with precompiled option before loading recheck_precompiled_assets plugin"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.configure(app)
|
|
57
|
+
precompiled_file = app.assets_opts[:precompiled]
|
|
58
|
+
prev_mtime = ::File.mtime(precompiled_file)
|
|
59
|
+
app.instance_exec do
|
|
60
|
+
opts[:assets] = opts[:assets].merge(:compiled=>_compiled_assets_initial_hash.replace(assets_opts[:compiled])).freeze
|
|
61
|
+
|
|
62
|
+
define_singleton_method(:recheck_precompiled_assets) do
|
|
63
|
+
new_mtime = ::File.mtime(precompiled_file)
|
|
64
|
+
if new_mtime != prev_mtime
|
|
65
|
+
prev_mtime = new_mtime
|
|
66
|
+
assets_opts[:compiled].replace(_precompiled_asset_metadata(precompiled_file))
|
|
67
|
+
|
|
68
|
+
# Unset the cached asset matchers, so new ones will be generated.
|
|
69
|
+
# This is needed in case the new precompiled metadata uses
|
|
70
|
+
# different files.
|
|
71
|
+
app::RodaRequest.instance_variable_set(:@assets_matchers, nil)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
singleton_class.send(:alias_method, :recheck_precompiled_assets, :recheck_precompiled_assets)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
module ClassMethods
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
# Wrap the precompiled asset metadata in a thread-safe hash.
|
|
82
|
+
def _precompiled_asset_metadata(file)
|
|
83
|
+
CompiledAssetsHash.new.replace(super)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Use a thread-safe wrapper of a hash for the :compiled assets option, since
|
|
87
|
+
# the recheck_precompiled_asset_metadata can modify it at runtime.
|
|
88
|
+
def _compiled_assets_initial_hash
|
|
89
|
+
CompiledAssetsHash.new
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
module RequestClassMethods
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
# Use a regexp that matches any digest. When the precompiled asset metadata
|
|
97
|
+
# file is updated, this allows requests for a previous precompiled asset to
|
|
98
|
+
# still work.
|
|
99
|
+
def _asset_regexp(type, key, _)
|
|
100
|
+
/#{Regexp.escape(key.sub(/\A#{type}/, ''))}\.[0-9a-fA-F]+\.#{type}/
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
register_plugin(:recheck_precompiled_assets, RecheckPrecompiledAssets)
|
|
106
|
+
end
|
|
107
|
+
end
|
data/lib/roda/plugins/render.rb
CHANGED
|
@@ -388,6 +388,8 @@ class Roda
|
|
|
388
388
|
instance.send(:retrieve_template, :template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
|
|
389
389
|
layout_method = opts[:render][:template_method_cache][:_roda_layout]
|
|
390
390
|
define_method(:_layout_method){layout_method}
|
|
391
|
+
private :_layout_method
|
|
392
|
+
alias_method(:_layout_method, :_layout_method)
|
|
391
393
|
opts[:render] = opts[:render].merge(:optimized_layout_method_created=>true)
|
|
392
394
|
end
|
|
393
395
|
end
|
data/lib/roda/version.rb
CHANGED
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.42.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: 2021-
|
|
11
|
+
date: 2021-03-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -212,6 +212,7 @@ extra_rdoc_files:
|
|
|
212
212
|
- doc/release_notes/3.4.0.txt
|
|
213
213
|
- doc/release_notes/3.40.0.txt
|
|
214
214
|
- doc/release_notes/3.41.0.txt
|
|
215
|
+
- doc/release_notes/3.42.0.txt
|
|
215
216
|
- doc/release_notes/3.5.0.txt
|
|
216
217
|
- doc/release_notes/3.6.0.txt
|
|
217
218
|
- doc/release_notes/3.7.0.txt
|
|
@@ -260,6 +261,7 @@ files:
|
|
|
260
261
|
- doc/release_notes/3.4.0.txt
|
|
261
262
|
- doc/release_notes/3.40.0.txt
|
|
262
263
|
- doc/release_notes/3.41.0.txt
|
|
264
|
+
- doc/release_notes/3.42.0.txt
|
|
263
265
|
- doc/release_notes/3.5.0.txt
|
|
264
266
|
- doc/release_notes/3.6.0.txt
|
|
265
267
|
- doc/release_notes/3.7.0.txt
|
|
@@ -341,6 +343,7 @@ files:
|
|
|
341
343
|
- lib/roda/plugins/precompile_templates.rb
|
|
342
344
|
- lib/roda/plugins/public.rb
|
|
343
345
|
- lib/roda/plugins/r.rb
|
|
346
|
+
- lib/roda/plugins/recheck_precompiled_assets.rb
|
|
344
347
|
- lib/roda/plugins/relative_path.rb
|
|
345
348
|
- lib/roda/plugins/render.rb
|
|
346
349
|
- lib/roda/plugins/render_each.rb
|