roda 3.63.0 → 3.65.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: 6e19674abcd02c79572ada44fe13fc8188a4cc91b780a3fbaa39da206cf7457f
4
- data.tar.gz: ffd0e850b4aab5e82b3f5cf307145853df9d420389ff8eb6170ec53d3e29ca57
3
+ metadata.gz: d1c9c4301b4c90cb2f2c7a2d190986b4b6c68c4e1eb4b0be59bdba2aebdf6780
4
+ data.tar.gz: 576b15ba70cdab634638bce683ba8ee8ac93feb9fe5f3ae8982cf6ae07c6d686
5
5
  SHA512:
6
- metadata.gz: d91087a996b037de3c0ecc3ca5e029f6b4bb40c5da1618048d70c0aa42ac5dcc581b6ed67e55cd9236da5463c3c224c62b09f85797daeffcb9a8fb98a16bca03
7
- data.tar.gz: 62d2e2fdb0efa867299a764d4f7b36fc1a1e680147d32703d29451e29d2e3090a0f337c2c87ac46929a5a504b6461f92d18b50a14c62f422de4c114e43892c91
6
+ metadata.gz: 91b24c2bbcb2d2c27c14f242d620fab9d5e838f68bc102887018e41e4e05f5eb93718ab312c727a32ac4ab6df0dbcf4d0bb134499674dee71e991e953ecac85b
7
+ data.tar.gz: 9fe4592c67425c171926368d1121841dcafae686eb6822439536c24040788049041f34dffae22fde1ba2905f63c0e3abd13a5938ea263f4b143fdb94219e66f1
data/CHANGELOG CHANGED
@@ -1,3 +1,19 @@
1
+ = 3.65.0 (2023-02-13)
2
+
3
+ * Make indifferent_params plugin work with changes in rack main branch (jeremyevans)
4
+
5
+ * Add autoload_named_routes plugin for autoloading file for a named route when there is a request for that route (jeremyevans)
6
+
7
+ * Make path method in path plugin accept class name string/symbol with :class_name option to register classes without forcing autoloads (jeremyevans)
8
+
9
+ = 3.64.0 (2023-01-12)
10
+
11
+ * Automatically expand paths for autoload_hash_branches files, so that relative paths work (jeremyevans)
12
+
13
+ * Make autoload_hash_branches plugin eagerly load the branches when freezing the application (jeremyevans)
14
+
15
+ * Add erb_h plugin for faster (if slightly less safe) html escaping using erb/escape (jeremyevans)
16
+
1
17
  = 3.63.0 (2022-12-16)
2
18
 
3
19
  * Make mailer plugin set configured content type for body part for emails with attachments when using mail 2.8+ (jeremyevans)
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2022 Jeremy Evans
1
+ Copyright (c) 2014-2023 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,26 @@
1
+ = New Features
2
+
3
+ * An erb_h plugin has been added for faster HTML escaping using
4
+ erb/escape. erb 4 added erb/escape and it is included in Ruby 3.2.
5
+
6
+ The erb_h plugin is added as a separate plugin because it changes
7
+ the behavior of the h method. The h method added by the h plugin
8
+ will always return a new string, but the h method added by the
9
+ erb_h plugin will return the argument if the argument is a
10
+ string that does not need escaping. By avoiding unnecessary
11
+ string allocations, use of the erb_h plugin can speed up HTML
12
+ escaping.
13
+
14
+ = Other Improvements
15
+
16
+ * The autoload_hash_branches plugin added in Roda 3.63.0 will now
17
+ eagerly load the hash branches when freezing the application,
18
+ allowing the application to continue to work after being frozen.
19
+ Additionally, file paths for the hash branches will now be
20
+ automatically expanded, allowing the use of relative file paths.
21
+
22
+ = Backwards Compatibility
23
+
24
+ * The expanding of file paths in the autoload_hash_branches plugin
25
+ can break applications that were providing relative paths and
26
+ expecting them to be looked up using the Ruby load path.
@@ -0,0 +1,12 @@
1
+ = New Features
2
+
3
+ * An autoload_named_routes plugin has been added for autoloading files
4
+ for a named route setup by the named_routes plugin when there is a
5
+ request for that route.
6
+
7
+ = Other Improvements
8
+
9
+ * The path method in the path plugin now supports a :class_name option.
10
+ You can set this option to true and use a class name String/Symbol
11
+ to register paths for classes without referencing the related class,
12
+ useful when autoloading the class.
@@ -13,8 +13,8 @@ class Roda
13
13
  # You can specify a single hash branch for autoloading:
14
14
  #
15
15
  # plugin :autoload_hash_branches
16
- # autoload_hash_branch('branch_name', '/path/to/file')
17
- # autoload_hash_branch('namespace', 'branch_name', '/path/to/file')
16
+ # autoload_hash_branch('branch_name', '/absolute/path/to/file')
17
+ # autoload_hash_branch('namespace', 'branch_name', 'relative/path/to/file')
18
18
  #
19
19
  # You can also set the plugin to autoload load all hash branch files in a given directory.
20
20
  # This will look at each .rb file in the directory, and add an autoload for it, using the
@@ -26,18 +26,24 @@ class Roda
26
26
  # In both cases, when the autoloaded file is required, it should redefine the same
27
27
  # hash branch. If it does not, requests to the hash branch will result in a 404 error.
28
28
  #
29
- # This plugin will not work correctly when freezing applications, because it requires
30
- # modifying the class at runtime as hash branches are autoloaded.
29
+ # When freezing an application, all hash branches are automatically loaded, because
30
+ # autoloading hash branches does not work for frozen applications.
31
31
  module AutoloadHashBranches
32
32
  def self.load_dependencies(app)
33
33
  app.plugin :hash_branches
34
34
  end
35
35
 
36
+ def self.configure(app)
37
+ app.opts[:autoload_hash_branch_files] ||= []
38
+ end
39
+
36
40
  module ClassMethods
37
41
  # Autoload the given file when there is request for the hash branch.
38
42
  # The given file should configure the hash branch specified.
39
43
  def autoload_hash_branch(namespace='', segment, file)
40
44
  segment = "/#{segment}"
45
+ file = File.expand_path(file)
46
+ opts[:autoload_hash_branch_files] << file
41
47
  routes = opts[:hash_branches][namespace] ||= {}
42
48
  meth = routes[segment] = define_roda_method(routes[segment] || "hash_branch_#{namespace}_#{segment}", 1) do |r|
43
49
  loc = method(routes[segment]).source_location
@@ -59,6 +65,12 @@ class Roda
59
65
  end
60
66
  end
61
67
  end
68
+
69
+ # Eagerly load all hash branches when freezing the application.
70
+ def freeze
71
+ opts.delete(:autoload_hash_branch_files).each{|file| require file}
72
+ super
73
+ end
62
74
  end
63
75
  end
64
76
 
@@ -0,0 +1,65 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The autoload_named_routes plugin builds on the named_routes plugin and allows for
7
+ # delaying loading of a file containing a named route for an application until there
8
+ # is a request that uses the named route. This can be useful in development
9
+ # to improvement startup time by not loading all named routes up front. It can also be
10
+ # useful in testing subsets of an application by only loading the named routes being
11
+ # tested.
12
+ #
13
+ # You can specify a single hash branch for autoloading:
14
+ #
15
+ # plugin :autoload_named_route
16
+ # autoload_named_route(:route_name, '/absolute/path/to/file')
17
+ # autoload_named_route(:namespace, :route_name, 'relative/path/to/file')
18
+ #
19
+ # Note that unlike the +route+ method defined by the named_routes plugin, when providing
20
+ # a namespace, the namespace comes before the route name and not after.
21
+ #
22
+ # When the autoloaded file is required, it should redefine the same
23
+ # named route. If it does not, requests to the named route will be ignored (as if the
24
+ # related named route block was empty).
25
+ #
26
+ # When freezing an application, all named routes are automatically loaded, because
27
+ # autoloading named routes does not work for frozen applications.
28
+ module AutoloadNamedRoutes
29
+ def self.load_dependencies(app)
30
+ app.plugin :named_routes
31
+ end
32
+
33
+ def self.configure(app)
34
+ app.opts[:autoload_named_route_files] ||= []
35
+ end
36
+
37
+ module ClassMethods
38
+ # Autoload the given file when there is request for the named route.
39
+ # The given file should configure the named route specified.
40
+ def autoload_named_route(namespace=nil, name, file)
41
+ file = File.expand_path(file)
42
+ opts[:autoload_named_route_files] << file
43
+ routes = opts[:namespaced_routes][namespace] ||= {}
44
+ meth = routes[name] = define_roda_method(routes[name] || "named_routes_#{namespace}_#{name}", 1) do |r|
45
+ loc = method(routes[name]).source_location
46
+ require file
47
+ # Avoid infinite loop in case method is not overridden
48
+ if method(meth).source_location != loc
49
+ send(meth, r)
50
+ end
51
+ end
52
+ nil
53
+ end
54
+
55
+ # Eagerly load all autoloaded named routes when freezing the application.
56
+ def freeze
57
+ opts.delete(:autoload_named_route_files).each{|file| require file}
58
+ super
59
+ end
60
+ end
61
+ end
62
+
63
+ register_plugin(:autoload_named_routes, AutoloadNamedRoutes)
64
+ end
65
+ end
@@ -0,0 +1,43 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'erb/escape'
4
+
5
+ #
6
+ class Roda
7
+ module RodaPlugins
8
+ # The erb_h plugin adds an +h+ instance method that will HTML
9
+ # escape the input and return it. This is similar to the h
10
+ # plugin, but it uses erb/escape to implement the HTML escaping,
11
+ # which offers faster performance.
12
+ #
13
+ # To make sure that this speeds up applications using the h
14
+ # plugin, this depends on the h plugin, and overrides the
15
+ # h method.
16
+ #
17
+ # The following example will return "&lt;foo&gt;" as the body.
18
+ #
19
+ # plugin :erb_h
20
+ #
21
+ # route do |r|
22
+ # h('<foo>')
23
+ # end
24
+ #
25
+ # The faster performance offered by the erb_h plugin is due
26
+ # to erb/escape avoiding allocations if not needed (returning the
27
+ # input object if no escaping is needed). That behavior change
28
+ # can cause problems if you mutate the result of the h method
29
+ # (which can mutate the input), or mutate the input of the h
30
+ # method after calling it (which can mutate the result).
31
+ module ErbH
32
+ def self.load_dependencies(app)
33
+ app.plugin :h
34
+ end
35
+
36
+ module InstanceMethods
37
+ define_method(:h, ERB::Escape.instance_method(:html_escape))
38
+ end
39
+ end
40
+
41
+ register_plugin(:erb_h, ErbH)
42
+ end
43
+ end
@@ -401,7 +401,6 @@ END
401
401
 
402
402
  private
403
403
 
404
- # :nocov:
405
404
  if RUBY_VERSION >= '3.2'
406
405
  def exception_page_exception_message(exception)
407
406
  exception.detailed_message(highlight: false).to_s
@@ -413,6 +412,7 @@ END
413
412
  exception.message.to_s
414
413
  end
415
414
  end
415
+ # :nocov:
416
416
  end
417
417
 
418
418
  module RequestMethods
@@ -53,9 +53,18 @@ class Roda
53
53
 
54
54
  class Params < Rack::QueryParser::Params
55
55
  if Rack.release >= '3'
56
- def initialize
57
- @size = 0
58
- @params = Hash.new(&INDIFFERENT_PROC)
56
+ # rack main branch compatibility
57
+ # :nocov:
58
+ if Params < Hash
59
+ def initialize
60
+ super(&INDIFFERENT_PROC)
61
+ end
62
+ # :nocov:
63
+ else
64
+ def initialize
65
+ @size = 0
66
+ @params = Hash.new(&INDIFFERENT_PROC)
67
+ end
59
68
  end
60
69
  else
61
70
  def initialize(limit = Rack::Utils.key_space_limit)
@@ -26,6 +26,9 @@ class Roda
26
26
  # path Quux do |quux, path|
27
27
  # "/quux/#{quux.id}/#{path}"
28
28
  # end
29
+ # path 'FooBar', class_name: true do |foobar|
30
+ # "/foobar/#{foobar.id}"
31
+ # end
29
32
  #
30
33
  # route do |r|
31
34
  # r.post 'foo' do
@@ -65,9 +68,18 @@ class Roda
65
68
  #
66
69
  # Note that if :add_script_name, :relative, :url, or :url_only is used, the path method will also create a
67
70
  # <tt>_*_path</tt> private method.
71
+ #
72
+ # If the path class method is passed a string or symbol as the first argument, and the second argument
73
+ # is a hash with the :class_name option passed, the symbol/string is treated as a class name.
74
+ # This enables the use of class-based paths without forcing autoloads for the related
75
+ # classes. If the plugin is not registering classes by name, this will use the symbol or
76
+ # string to find the related class.
68
77
  module Path
69
78
  DEFAULT_PORTS = {'http' => 80, 'https' => 443}.freeze
70
79
 
80
+ # Regexp for valid constant names, to prevent code execution.
81
+ VALID_CONSTANT_NAME_REGEXP = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.freeze
82
+
71
83
  # Initialize the path classes when loading the plugin. Options:
72
84
  # :by_name :: Register classes by name, which is friendlier when reloading code (defaults to
73
85
  # true in development mode)
@@ -97,11 +109,20 @@ class Roda
97
109
 
98
110
  # Create a new instance method for the named path. See plugin module documentation for options.
99
111
  def path(name, path=nil, opts=OPTS, &block)
100
- if name.is_a?(Class)
101
- raise RodaError, "can't provide path or options when calling path with a class" unless path.nil? && opts.empty?
112
+ if name.is_a?(Class) || (path.is_a?(Hash) && (class_name = path[:class_name]))
113
+ raise RodaError, "can't provide path when calling path with a class" if path && !class_name
114
+ raise RodaError, "can't provide options when calling path with a class" unless opts.empty?
102
115
  raise RodaError, "must provide a block when calling path with a class" unless block
103
116
  if self.opts[:path_class_by_name]
104
- name = name.name
117
+ if class_name
118
+ name = name.to_s
119
+ else
120
+ name = name.name
121
+ end
122
+ elsif class_name
123
+ name = name.to_s
124
+ raise RodaError, "invalid class name passed when using class_name option" unless VALID_CONSTANT_NAME_REGEXP =~ name
125
+ name = Object.class_eval(name, __FILE__, __LINE__)
105
126
  end
106
127
  path_classes[name] = block
107
128
  self.opts[:path_class_methods][name] = define_roda_method("path_#{name}", :any, &block)
data/lib/roda/version.rb CHANGED
@@ -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 = 63
7
+ RodaMinorVersion = 65
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.63.0
4
+ version: 3.65.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: 2022-12-16 00:00:00.000000000 Z
11
+ date: 2023-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -236,6 +236,8 @@ extra_rdoc_files:
236
236
  - doc/release_notes/3.61.0.txt
237
237
  - doc/release_notes/3.62.0.txt
238
238
  - doc/release_notes/3.63.0.txt
239
+ - doc/release_notes/3.64.0.txt
240
+ - doc/release_notes/3.65.0.txt
239
241
  - doc/release_notes/3.7.0.txt
240
242
  - doc/release_notes/3.8.0.txt
241
243
  - doc/release_notes/3.9.0.txt
@@ -306,6 +308,8 @@ files:
306
308
  - doc/release_notes/3.61.0.txt
307
309
  - doc/release_notes/3.62.0.txt
308
310
  - doc/release_notes/3.63.0.txt
311
+ - doc/release_notes/3.64.0.txt
312
+ - doc/release_notes/3.65.0.txt
309
313
  - doc/release_notes/3.7.0.txt
310
314
  - doc/release_notes/3.8.0.txt
311
315
  - doc/release_notes/3.9.0.txt
@@ -323,6 +327,7 @@ files:
323
327
  - lib/roda/plugins/assets.rb
324
328
  - lib/roda/plugins/assets_preloading.rb
325
329
  - lib/roda/plugins/autoload_hash_branches.rb
330
+ - lib/roda/plugins/autoload_named_routes.rb
326
331
  - lib/roda/plugins/backtracking_array.rb
327
332
  - lib/roda/plugins/branch_locals.rb
328
333
  - lib/roda/plugins/caching.rb
@@ -347,6 +352,7 @@ files:
347
352
  - lib/roda/plugins/early_hints.rb
348
353
  - lib/roda/plugins/empty_root.rb
349
354
  - lib/roda/plugins/environments.rb
355
+ - lib/roda/plugins/erb_h.rb
350
356
  - lib/roda/plugins/error_email.rb
351
357
  - lib/roda/plugins/error_handler.rb
352
358
  - lib/roda/plugins/error_mail.rb
@@ -460,7 +466,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
460
466
  - !ruby/object:Gem::Version
461
467
  version: '0'
462
468
  requirements: []
463
- rubygems_version: 3.3.26
469
+ rubygems_version: 3.4.6
464
470
  signing_key:
465
471
  specification_version: 4
466
472
  summary: Routing tree web toolkit