roda 3.49.0 → 3.53.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: 2d3b9688bae8b0013acedfc6a5bcb45c374e0a73fd30e56985f0ebeee942ef8c
4
- data.tar.gz: acb8215250d1615f007a2ec01d2b6546376414d2fea23a4f2341af9efd951110
3
+ metadata.gz: 90bdf6d366ffc4bff40aa51721176291fadb80f56d7904965fe46a1385fe4172
4
+ data.tar.gz: ab1bea5320b4049e918ebb23d1b081c26d5401000f11b02c5f85a1e1b30899c3
5
5
  SHA512:
6
- metadata.gz: 3a5434bdcb6926d6c5e656c25b46e16b035ad54d74ed16bdc1cf46005b8ef605b3371a628cae52d65803064aa3d2eac8a56c2e8e1e55b6f3a82c04a74c636855
7
- data.tar.gz: 9dc3773fae04325373adb8a7a57d52166bb65c238b959999adf6f6f17a3be29fcdedcea677eeeaaa84f6a01b5accb4aff2594817165b8a77a45106a3d4a9dea3
6
+ metadata.gz: 13bc3beb138174dc8cadfc309458bd1821cbe8b6f80f1cb704752979bf085710181d5fd9df71a3cc1fba2be3b258721f36c8758e202961f9389f23b7555ee78b
7
+ data.tar.gz: 7129008315908bf7ebd6c0115cd8eb531a6357617a5f9ce3a0ffae3703a5cd68793af0d43ac4703752e280a5cc6090234b60640fe25384c4fa8aabe8e04b94af
data/CHANGELOG CHANGED
@@ -1,3 +1,37 @@
1
+ = 3.53.0 (2022-02-14)
2
+
3
+ * Make indifferent_params plugin support rack main branch (jeremyevans)
4
+
5
+ * Add additional_view_directories plugin, for checking multiple view directories for templates (jeremyevans) (#229)
6
+
7
+ = 3.52.0 (2022-01-14)
8
+
9
+ * Fix return value of Roda.freeze when multi_route plugin is used (jeremyevans) (#240)
10
+
11
+ * Use faster OpenSSL::Digest instead of Digest for assets plugin SRI support (jeremyevans)
12
+
13
+ * Drop development dependency on haml (jeremyevans)
14
+
15
+ * Make the path method in the path plugin handle blocks that accept keyword arguments in Ruby 3+ (adam12) (#227)
16
+
17
+ * Support typecast_params :date_parse_input_handler plugin option for handling input to date parsing methods (jeremyevans)
18
+
19
+ = 3.51.0 (2021-12-15)
20
+
21
+ * Avoid method redefinition warning in error_handler plugin in verbose warning mode (jeremyevans)
22
+
23
+ * Allow run in multi_run plugin to be called without an app to remove existing handler (jeremyevans)
24
+
25
+ * Allow route in named_routes plugin to be called without a block to remove existing handler (jeremyevans)
26
+
27
+ = 3.50.0 (2021-11-12)
28
+
29
+ * Add capture_erb plugin for capturing ERB template blocks, instead of injecting them into the template output (jeremyevans)
30
+
31
+ * Add inject_erb plugin for injecting content directly into ERB template output (jeremyevans)
32
+
33
+ * Allow hash_branch and hash_path in hash_routes plugin to be called without a block to remove existing handler (jeremyevans)
34
+
1
35
  = 3.49.0 (2021-10-13)
2
36
 
3
37
  * Switch block_given? to defined?(yield) (jeremyevans)
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2021 Jeremy Evans
1
+ Copyright (c) 2014-2022 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
 
data/README.rdoc CHANGED
@@ -12,7 +12,8 @@ maintainable web applications in ruby.
12
12
  Website :: http://roda.jeremyevans.net
13
13
  Source :: http://github.com/jeremyevans/roda
14
14
  Bugs :: http://github.com/jeremyevans/roda/issues
15
- Google Group :: http://groups.google.com/group/ruby-roda
15
+ Discussion Forum (GitHub Discussions) :: https://github.com/jeremyevans/roda/discussions
16
+ Alternate Discussion Forum (Google Group) :: http://groups.google.com/group/ruby-roda
16
17
 
17
18
  == Goals
18
19
 
@@ -0,0 +1,21 @@
1
+ = New Features
2
+
3
+ * An inject_erb plugin has been added, adding an inject_erb method
4
+ that allows for injecting content directly into the template output
5
+ for the template currently being rendered. This allows you to more
6
+ easily wrap blocks in templates, by calling methods that accept
7
+ template blocks and injecting content before and after the block.
8
+
9
+ * A capture_erb plugin has been added, adding a capture_erb method
10
+ for capturing a template block in an erb template and returning
11
+ the content appended during the block as a string, instead of
12
+ having the content of the template block be included directly into
13
+ the template output. This can be combined with the inject_erb
14
+ plugin to inject modified versions of captured blocks into template
15
+ output.
16
+
17
+ * The hash_routes plugin now allows calling hash_branch and hash_path
18
+ without a block in order to remove the existing route handler. This
19
+ is designed to be used with code reloading libraries, so that if a
20
+ route file is deleted, the related hash branches/paths are also
21
+ removed, without having to reload all route files.
@@ -0,0 +1,20 @@
1
+ = New Features
2
+
3
+ * The named_routes plugin now allows calling route without a block
4
+ to remove the existing route handler. The multi_run plugin
5
+ now allows calling run without an app to remove an existing handler.
6
+ These changes are designed to better support code reloading
7
+ libraries, so that if the related file is deleted, the related
8
+ handlers are also removed, without having to reload the entire
9
+ application.
10
+
11
+ = Other Improvements
12
+
13
+ * The error_handler plugin now avoids a method redefinition warning
14
+ in verbose warning mode.
15
+
16
+ = Other
17
+
18
+ * Roda's primary discussion forum is now GitHub Discussions. The
19
+ ruby-roda Google Group is still available for users who would
20
+ prefer to use that instead.
@@ -0,0 +1,20 @@
1
+ = New Features
2
+
3
+ * The typecast_params plugin now supports a :date_parse_input_handler
4
+ option that will be called with all input that will be passed to
5
+ the date parsing methods. You can use this option to automatically
6
+ truncate input, if that is perferable to raising an error (which is
7
+ how recent versions of Ruby handle too-long input).
8
+
9
+ = Other Improvements
10
+
11
+ * The path helper methods added by the path plugin now support
12
+ blocks that use keyword arguments on Ruby 3+.
13
+
14
+ * The assets plugin now uses OpenSSL::Digest instead of Digest (if
15
+ available) for calculating SRI digests. This is faster on Ruby 3+,
16
+ where Digest no longer uses the faster OpenSSL::Digest automatically
17
+ if available.
18
+
19
+ * Roda.freeze now returns self when the multi_route plugin is used.
20
+ This was broken (not returning self) starting in 3.48.0.
@@ -0,0 +1,14 @@
1
+ = New Features
2
+
3
+ * An additional_view_directories plugin has been added, which allows
4
+ you to specify additional directories to look in for templates.
5
+ If the template path does not exist when using the default view
6
+ directory, then each additional view directory will be checked,
7
+ returning the first path that exists:
8
+
9
+ plugin :additional_view_directories, ['admin_views', 'public_views']
10
+
11
+ = Other Improvements
12
+
13
+ * The indifferent_params plugin now avoids a deprecation warning when
14
+ using the rack main branch, which will become Rack 3.
@@ -0,0 +1,68 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The additional_view_directories plugin allows for specifying additional view
7
+ # directories to look in for templates. When rendering a template, it will
8
+ # first try the :views directory specified in the render plugin. If the template
9
+ # file to be rendered does not exist in that directory, it will try each additional
10
+ # view directory specified in this plugin, in order, using the path to the first
11
+ # template file that exists in the file system. If no such path is found, it
12
+ # uses the default path specified by the render plugin.
13
+ #
14
+ # Example:
15
+ #
16
+ # plugin :render, :views=>'dir'
17
+ # plugin :additional_view_directories, ['dir1', 'dir2', 'dir3']
18
+ #
19
+ # route do |r|
20
+ # # Will check the following in order, using path for first
21
+ # # template file that exists:
22
+ # # * dir/t.erb
23
+ # # * dir1/t.erb
24
+ # # * dir2/t.erb
25
+ # # * dir3/t.erb
26
+ # render :t
27
+ # end
28
+ module AdditionalViewDirectories
29
+ # Depend on the render plugin, since this plugin only makes
30
+ # sense when the render plugin is used.
31
+ def self.load_dependencies(app, view_dirs)
32
+ app.plugin :render
33
+ end
34
+
35
+ # Set the additional view directories to look in. Each additional view directory
36
+ # is also added as an allowed path.
37
+ def self.configure(app, view_dirs)
38
+ view_dirs = app.opts[:additional_view_directories] = view_dirs.map{|f| app.expand_path(f, nil)}.freeze
39
+ opts = app.opts[:render]
40
+ app.opts[:render] = opts.merge(:allowed_paths=>(opts[:allowed_paths] + view_dirs).uniq.freeze)
41
+ opts.freeze
42
+ end
43
+
44
+ module InstanceMethods
45
+ private
46
+
47
+ # If the template path does not exist, try looking for the template
48
+ # in each of the additional view directories, in order, returning
49
+ # the first path that exists. If no additional directory includes
50
+ # the template, return the original path.
51
+ def template_path(opts)
52
+ orig_path = super
53
+
54
+ unless File.file?(orig_path)
55
+ self.opts[:additional_view_directories].each do |view_dir|
56
+ path = super(opts.merge(:views=>view_dir))
57
+ return path if File.file?(path)
58
+ end
59
+ end
60
+
61
+ orig_path
62
+ end
63
+ end
64
+ end
65
+
66
+ register_plugin(:additional_view_directories, AdditionalViewDirectories)
67
+ end
68
+ end
@@ -641,9 +641,17 @@ class Roda
641
641
  # a different digest type or to return a static string if you don't
642
642
  # want to use a unique value.
643
643
  def asset_digest(content)
644
- require 'digest/sha2'
645
644
  algo = assets_opts[:sri] || :sha256
646
- ::Digest.const_get(algo.to_s.upcase).hexdigest(content)
645
+ digest = begin
646
+ require 'openssl'
647
+ ::OpenSSL::Digest
648
+ # :nocov:
649
+ rescue LoadError
650
+ require 'digest/sha2'
651
+ ::Digest
652
+ # :nocov:
653
+ end
654
+ digest.const_get(algo.to_s.upcase).hexdigest(content)
647
655
  end
648
656
  end
649
657
 
@@ -0,0 +1,41 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The capture_erb plugin allows you to capture the content of a block
7
+ # in an ERB template, and return it as a value, instead of
8
+ # injecting the template block into the template output.
9
+ #
10
+ # <% value = capture_erb do %>
11
+ # Some content here.
12
+ # <% end %>
13
+ #
14
+ # +capture_erb+ can be used inside other methods that are called
15
+ # inside templates. It can be combined with the inject_erb plugin
16
+ # to wrap template blocks with arbitrary output and then inject the
17
+ # wrapped output into the template.
18
+ module CaptureERB
19
+ def self.load_dependencies(app)
20
+ app.plugin :render
21
+ end
22
+
23
+ module InstanceMethods
24
+ # Temporarily replace the ERB output buffer
25
+ # with an empty string, and then yield to the block.
26
+ # Return the value of the block, converted to a string.
27
+ # Restore the previous ERB output buffer before returning.
28
+ def capture_erb
29
+ outvar = render_opts[:template_opts][:outvar]
30
+ buf_was = instance_variable_get(outvar)
31
+ instance_variable_set(outvar, String.new)
32
+ yield.to_s
33
+ ensure
34
+ instance_variable_set(outvar, buf_was) if outvar && buf_was
35
+ end
36
+ end
37
+ end
38
+
39
+ register_plugin(:capture_erb, CaptureERB)
40
+ end
41
+ end
@@ -55,10 +55,10 @@ class Roda
55
55
  #
56
56
  # plugin :content_for, append: false
57
57
  module ContentFor
58
- # Depend on the render plugin, since this plugin only makes
59
- # sense when the render plugin is used.
58
+ # Depend on the capture_erb plugin, since it uses capture_erb
59
+ # to capture the content.
60
60
  def self.load_dependencies(app, _opts = OPTS)
61
- app.plugin :render
61
+ app.plugin :capture_erb
62
62
  end
63
63
 
64
64
  # Configure whether to append or overwrite if content_for
@@ -72,18 +72,12 @@ class Roda
72
72
  # under the given key. If called without a block, retrieve
73
73
  # stored content with the given key, or return nil if there
74
74
  # is no content stored with that key.
75
- def content_for(key, value=nil)
75
+ def content_for(key, value=nil, &block)
76
76
  append = opts[:append_content_for]
77
77
 
78
- if defined?(yield) || value
79
- if defined?(yield)
80
- outvar = render_opts[:template_opts][:outvar]
81
- buf_was = instance_variable_get(outvar)
82
-
83
- # Use temporary output buffer for ERB-based rendering systems
84
- instance_variable_set(outvar, String.new)
85
- value = yield.to_s
86
- instance_variable_set(outvar, buf_was)
78
+ if block || value
79
+ if block
80
+ value = capture_erb(&block)
87
81
  end
88
82
 
89
83
  @_content_for ||= {}
@@ -62,6 +62,7 @@ class Roda
62
62
  # the exception in the scope of the Roda instance.
63
63
  def error(&block)
64
64
  define_method(:handle_error, &block)
65
+ alias_method(:handle_error, :handle_error)
65
66
  private :handle_error
66
67
  end
67
68
  end
@@ -394,20 +394,32 @@ class Roda
394
394
  dsl
395
395
  end
396
396
 
397
- # Add branch handler for the given namespace and segment.
397
+ # Add branch handler for the given namespace and segment. If called without
398
+ # a block, removes the existing branch handler if it exists.
398
399
  def hash_branch(namespace='', segment, &block)
399
400
  segment = "/#{segment}"
400
401
  routes = opts[:hash_branches][namespace] ||= {}
401
- routes[segment] = define_roda_method(routes[segment] || "hash_branch_#{namespace}_#{segment}", 1, &convert_route_block(block))
402
+ if block
403
+ routes[segment] = define_roda_method(routes[segment] || "hash_branch_#{namespace}_#{segment}", 1, &convert_route_block(block))
404
+ elsif meth = routes[segment]
405
+ routes.delete(segment)
406
+ remove_method(meth)
407
+ end
402
408
  end
403
409
 
404
410
  # Add path handler for the given namespace and path. When the
405
411
  # r.hash_paths method is called, checks the matching namespace
406
412
  # for the full remaining path, and dispatch to that block if
407
- # there is one.
413
+ # there is one. If called without a block, removes the existing
414
+ # path handler if it exists.
408
415
  def hash_path(namespace='', path, &block)
409
416
  routes = opts[:hash_paths][namespace] ||= {}
410
- routes[path] = define_roda_method(routes[path] || "hash_path_#{namespace}_#{path}", 1, &convert_route_block(block))
417
+ if block
418
+ routes[path] = define_roda_method(routes[path] || "hash_path_#{namespace}_#{path}", 1, &convert_route_block(block))
419
+ elsif meth = routes[path]
420
+ routes.delete(path)
421
+ remove_method(meth)
422
+ end
411
423
  end
412
424
  end
413
425
 
@@ -52,17 +52,29 @@ class Roda
52
52
  end
53
53
 
54
54
  class Params < Rack::QueryParser::Params
55
- def initialize(limit = Rack::Utils.key_space_limit)
56
- @limit = limit
57
- @size = 0
58
- @params = Hash.new(&INDIFFERENT_PROC)
55
+ # :nocov:
56
+ if Rack.release >= '2.3'
57
+ def initialize
58
+ @size = 0
59
+ @params = Hash.new(&INDIFFERENT_PROC)
60
+ end
61
+ else
62
+ # :nocov:
63
+ def initialize(limit = Rack::Utils.key_space_limit)
64
+ @limit = limit
65
+ @size = 0
66
+ @params = Hash.new(&INDIFFERENT_PROC)
67
+ end
59
68
  end
60
69
  end
61
70
 
62
71
  end
63
72
 
64
73
  module RequestMethods
65
- QUERY_PARSER = Rack::Utils.default_query_parser = QueryParser.new(QueryParser::Params, 65536, 100)
74
+ # :nocov:
75
+ query_parser = Rack.release >= '2.3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32)
76
+ # :nocov:
77
+ QUERY_PARSER = Rack::Utils.default_query_parser = query_parser
66
78
 
67
79
  private
68
80
 
@@ -0,0 +1,33 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The inject_erb plugin allows you to inject content directly
7
+ # into the template output:
8
+ #
9
+ # <% inject_erb("Some HTML Here") %>
10
+ #
11
+ # This will inject <tt>Some HTML Here</tt> into the template output,
12
+ # even though the tag being used is <tt><%</tt> and not <tt><%=</tt>.
13
+ #
14
+ # This method can be used inside methods, such as to wrap calls to
15
+ # methods that accept template blocks, to inject code before and after
16
+ # the template blocks.
17
+ module InjectERB
18
+ def self.load_dependencies(app)
19
+ app.plugin :render
20
+ end
21
+
22
+ module InstanceMethods
23
+ # Inject into the template output for the template currently being
24
+ # rendered.
25
+ def inject_erb(value)
26
+ instance_variable_get(render_opts[:template_opts][:outvar]) << value.to_s
27
+ end
28
+ end
29
+ end
30
+
31
+ register_plugin(:inject_erb, InjectERB)
32
+ end
33
+ end
@@ -98,6 +98,7 @@ class Roda
98
98
  self::RodaRequest.named_route_regexp(k)
99
99
  end
100
100
  self::RodaRequest.instance_variable_get(:@namespaced_route_regexps).freeze
101
+ self
101
102
  end
102
103
 
103
104
  # Copy the named routes into the subclass when inheriting.
@@ -45,6 +45,9 @@ class Roda
45
45
  # subtrees, multi_run is a better approach, but it does not let you set instance
46
46
  # variables in the main Roda app and have those instance variables usable in
47
47
  # the routing subtrees.
48
+ #
49
+ # To handle development environments that reload code, you can call the
50
+ # +run+ class method without an app to remove dispatching for the prefix.
48
51
  module MultiRun
49
52
  # Initialize the storage for the dispatched applications
50
53
  def self.configure(app)
@@ -67,8 +70,12 @@ class Roda
67
70
 
68
71
  # Add a rack application to dispatch to for the given prefix when
69
72
  # r.multi_run is called.
70
- def run(prefix, app)
71
- multi_run_apps[prefix.to_s] = app
73
+ def run(prefix, app=nil)
74
+ if app
75
+ multi_run_apps[prefix.to_s] = app
76
+ else
77
+ multi_run_apps.delete(prefix.to_s)
78
+ end
72
79
  self::RodaRequest.refresh_multi_run_regexp!
73
80
  end
74
81
  end
@@ -38,6 +38,9 @@ class Roda
38
38
  # Note that in multi-threaded code, you should not attempt to add a
39
39
  # named route after accepting requests.
40
40
  #
41
+ # To handle development environments that reload code, you can call the
42
+ # +route+ class method without a block to remove an existing named route.
43
+ #
41
44
  # == Routing Files
42
45
  #
43
46
  # The convention when using the named_routes plugin is to have a single
@@ -124,7 +127,7 @@ class Roda
124
127
  # The names for the currently stored named routes
125
128
  def named_routes(namespace=nil)
126
129
  unless routes = opts[:namespaced_routes][namespace]
127
- raise RodaError, "unsupported multi_route namespace used: #{namespace.inspect}"
130
+ raise RodaError, "unsupported named_routes namespace used: #{namespace.inspect}"
128
131
  end
129
132
  routes.keys
130
133
  end
@@ -140,7 +143,12 @@ class Roda
140
143
  def route(name=nil, namespace=nil, &block)
141
144
  if name
142
145
  routes = opts[:namespaced_routes][namespace] ||= {}
143
- routes[name] = define_roda_method(routes[name] || "multi_route_#{namespace}_#{name}", 1, &convert_route_block(block))
146
+ if block
147
+ routes[name] = define_roda_method(routes[name] || "named_routes_#{namespace}_#{name}", 1, &convert_route_block(block))
148
+ elsif meth = routes[name]
149
+ routes.delete(name)
150
+ remove_method(meth)
151
+ end
144
152
  else
145
153
  super(&block)
146
154
  end
@@ -41,12 +41,12 @@ class Roda
41
41
  # end
42
42
  #
43
43
  # r.post 'baz' do
44
- # bar = Baz[1]
44
+ # baz = Baz[1]
45
45
  # r.redirect path(baz, 'c', 'd') # /baz/1/c/d
46
46
  # end
47
47
  #
48
48
  # r.post 'quux' do
49
- # bar = Quux[1]
49
+ # quux = Quux[1]
50
50
  # r.redirect url(quux, '/bar') # http://example.com/quux/1/bar
51
51
  # end
52
52
  # end
@@ -148,11 +148,17 @@ class Roda
148
148
  # Allow calling private _method to get path
149
149
  relative_path(request.script_name.to_s + send(_meth, *a, &blk))
150
150
  end
151
+ # :nocov:
152
+ ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
153
+ # :nocov:
151
154
  elsif add_script_name
152
155
  define_method(meth) do |*a, &blk|
153
156
  # Allow calling private _method to get path
154
157
  request.script_name.to_s + send(_meth, *a, &blk)
155
158
  end
159
+ # :nocov:
160
+ ruby2_keywords(meth) if respond_to?(:ruby2_keywords, true)
161
+ # :nocov:
156
162
  else
157
163
  define_method(meth, &block)
158
164
  end
@@ -171,6 +177,9 @@ class Roda
171
177
  end
172
178
 
173
179
  define_method(url_meth, &url_block)
180
+ # :nocov:
181
+ ruby2_keywords(url_meth) if respond_to?(:ruby2_keywords, true)
182
+ # :nocov:
174
183
  end
175
184
 
176
185
  nil
@@ -47,7 +47,7 @@ class Roda
47
47
  # The following plugin options are supported:
48
48
  #
49
49
  # :allowed_paths :: Set the template paths to allow. Attempts to render paths outside
50
- # of this directory will raise an error. Defaults to the +:views+ directory.
50
+ # of these paths will raise an error. Defaults to the +:views+ directory.
51
51
  # :cache :: nil/false to explicitly disable premanent template caching. By default, permanent
52
52
  # template caching is disabled by default if RACK_ENV is development. When permanent
53
53
  # template caching is disabled, for templates with paths in the file system, the
@@ -59,9 +59,9 @@ class Roda
59
59
  # templates, defaults to 'erb'.
60
60
  # :escape :: Use Erubi as the ERB template engine, and enable escaping by default,
61
61
  # which makes <tt><%= %></tt> escape output and <tt><%== %></tt> not escape output.
62
- # If given, sets the <tt>:escape=>true</tt> option for all template engines, which
62
+ # If given, sets the <tt>escape: true</tt> option for all template engines, which
63
63
  # can break some non-ERB template engines. You can use a string or array of strings
64
- # as the value for this option to only set the <tt>:escape=>true</tt> option for those
64
+ # as the value for this option to only set the <tt>escape: true</tt> option for those
65
65
  # specific template engines.
66
66
  # :layout :: The base name of the layout file, defaults to 'layout'. This can be provided as a hash
67
67
  # with the :template or :inline options.
@@ -130,6 +130,84 @@ class Roda
130
130
  # only argument, you can speed things up by specifying a +:cache_key+ option in
131
131
  # the hash, making sure the +:cache_key+ is unique to the template you are
132
132
  # rendering.
133
+ #
134
+ # = Accepting Template Blocks in Methods
135
+ #
136
+ # If you are used to Rails, you may be surprised that this type of template code
137
+ # doesn't work in Roda:
138
+ #
139
+ # <%= some_method do %>
140
+ # Some HTML
141
+ # <% end %>
142
+ #
143
+ # The reason this doesn't work is that this is not valid ERB syntax, it is Rails syntax,
144
+ # and requires attempting to parse the <tt>some_method do</tt> Ruby code with a regular
145
+ # expression. Since Roda uses ERB syntax, it does not support this.
146
+ #
147
+ # In general, these methods are used to wrap the content of the block and
148
+ # inject the content into the output. To get similar behavior with Roda, you have
149
+ # a few different options you can use.
150
+ #
151
+ # == Directly Inject Template Output
152
+ #
153
+ # You can switch from a <tt><%=</tt> tag to using a <tt><%</tt> tag:
154
+ #
155
+ # <% some_method do %>
156
+ # Some HTML
157
+ # <% end %>
158
+ #
159
+ # While this would output <tt>Some HTML</tt> into the template, it would not be able
160
+ # to inject content before or after the block. However, you can use the inject_erb_plugin
161
+ # to handle the injection:
162
+ #
163
+ # def some_method
164
+ # inject_erb "content before block"
165
+ # yield
166
+ # inject_erb "content after block"
167
+ # end
168
+ #
169
+ # If you need to modify the captured block before injecting it, you can use the
170
+ # capture_erb plugin to capture content from the template block, and modify that content,
171
+ # then use inject_erb to inject it into the template output:
172
+ #
173
+ # def some_method(&block)
174
+ # inject_erb "content before block"
175
+ # inject_erb capture_erb(&block).upcase
176
+ # inject_erb "content after block"
177
+ # end
178
+ #
179
+ # This is the recommended approach for handling this type of method, if you want to keep
180
+ # the template block in the same template.
181
+ #
182
+ # == Separate Block Output Into Separate Template
183
+ #
184
+ # By moving the <tt>Some HTML</tt> into a separate template, you can render that
185
+ # template inside the block:
186
+ #
187
+ # <%= some_method{render('template_name')} %>
188
+ #
189
+ # It's also possible to use an inline template:
190
+ #
191
+ # <%= some_method do render(:inline=><<-END)
192
+ # Some HTML
193
+ # END
194
+ # end %>
195
+ #
196
+ # This approach is useful if it makes sense to separate the template block into its
197
+ # own template. You lose the ability to use local variable from outside the
198
+ # template block inside the template block with this approach.
199
+ #
200
+ # == Separate Header and Footer
201
+ #
202
+ # You can define two separate methods, one that outputs the content before the block,
203
+ # and one that outputs the content after the block, and use those instead of a single
204
+ # call:
205
+ #
206
+ # <%= some_method_before %>
207
+ # Some HTML
208
+ # <%= some_method_after %>
209
+ #
210
+ # This is the simplest option to setup, but it is fairly tedious to use.
133
211
  module Render
134
212
  # Support for using compiled methods directly requires Ruby 2.3 for the
135
213
  # method binding to work, and Tilt 1.2 for Tilt::Template#compiled_method.
@@ -6,8 +6,7 @@ class Roda
6
6
  # The status_303 plugin sets the default redirect status to be 303
7
7
  # rather than 302 when the request is not a GET and the
8
8
  # redirection occurs on an HTTP 1.1 connection as per RFC 7231.
9
- # The author knows of no cases where this actually matters in
10
- # practice.
9
+ # There are some frontend frameworks that require this behavior.
11
10
  #
12
11
  # Example:
13
12
  #
@@ -265,6 +265,23 @@ class Roda
265
265
  # If you would like to skip this check and allow null bytes in param string values,
266
266
  # you can do by passing the <tt>:allow_null_bytes</tt> option when loading the plugin.
267
267
  #
268
+ # You can use the :date_parse_input_handler option to specify custom handling of date
269
+ # parsing input. Modern versions of Ruby and the date gem internally raise if the input to
270
+ # date parsing methods is too large to prevent denial of service. If you are using an
271
+ # older version of Ruby, you can use this option to enforce the same check:
272
+ #
273
+ # plugin :typecast_params, date_parse_input_handler: proc {|string|
274
+ # raise ArgumentError, "too big" if string.bytesize > 128
275
+ # string
276
+ # }
277
+ #
278
+ # You can also use this option to modify the input, such as truncating it to the first
279
+ # 128 bytes:
280
+ #
281
+ # plugin :typecast_params, date_parse_input_handler: proc {|string|
282
+ # string.b[0, 128]
283
+ # }
284
+ #
268
285
  # By design, typecast_params only deals with string keys, it is not possible to use
269
286
  # symbol keys as arguments to the conversion methods and have them converted.
270
287
  module TypecastParams
@@ -384,6 +401,14 @@ class Roda
384
401
  end
385
402
  end
386
403
 
404
+ module DateParseInputHandler
405
+ # Pass input string to date parsing through handle_date_parse_input.
406
+ def _string_parse!(klass, v)
407
+ v = handle_date_parse_input(v)
408
+ super
409
+ end
410
+ end
411
+
387
412
  # Class handling conversion of submitted parameters to desired types.
388
413
  class Params
389
414
  # Handle conversions for the given type using the given block.
@@ -999,11 +1024,16 @@ class Roda
999
1024
  when ''
1000
1025
  nil
1001
1026
  when String
1002
- klass.parse(v)
1027
+ _string_parse!(klass, v)
1003
1028
  else
1004
1029
  raise Error, "unexpected value received: #{v.inspect}"
1005
1030
  end
1006
1031
  end
1032
+
1033
+ # Handle parsing for string values passed to parse!.
1034
+ def _string_parse!(klass, v)
1035
+ klass.parse(v)
1036
+ end
1007
1037
  end
1008
1038
 
1009
1039
  # Set application-specific Params subclass unless one has been set,
@@ -1019,6 +1049,14 @@ class Roda
1019
1049
  if opts[:allow_null_bytes]
1020
1050
  app::TypecastParams.send(:include, AllowNullByte)
1021
1051
  end
1052
+ if opts[:date_parse_input_handler]
1053
+ app::TypecastParams.class_eval do
1054
+ include DateParseInputHandler
1055
+ define_method(:handle_date_parse_input, &opts[:date_parse_input_handler])
1056
+ private :handle_date_parse_input
1057
+ alias handle_date_parse_input handle_date_parse_input
1058
+ end
1059
+ end
1022
1060
  end
1023
1061
 
1024
1062
  module ClassMethods
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 = 49
7
+ RodaMinorVersion = 53
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.49.0
4
+ version: 3.53.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-10-13 00:00:00.000000000 Z
11
+ date: 2022-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -94,20 +94,6 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: haml
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rack_csrf
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -221,6 +207,10 @@ extra_rdoc_files:
221
207
  - doc/release_notes/3.48.0.txt
222
208
  - doc/release_notes/3.49.0.txt
223
209
  - doc/release_notes/3.5.0.txt
210
+ - doc/release_notes/3.50.0.txt
211
+ - doc/release_notes/3.51.0.txt
212
+ - doc/release_notes/3.52.0.txt
213
+ - doc/release_notes/3.53.0.txt
224
214
  - doc/release_notes/3.6.0.txt
225
215
  - doc/release_notes/3.7.0.txt
226
216
  - doc/release_notes/3.8.0.txt
@@ -277,6 +267,10 @@ files:
277
267
  - doc/release_notes/3.48.0.txt
278
268
  - doc/release_notes/3.49.0.txt
279
269
  - doc/release_notes/3.5.0.txt
270
+ - doc/release_notes/3.50.0.txt
271
+ - doc/release_notes/3.51.0.txt
272
+ - doc/release_notes/3.52.0.txt
273
+ - doc/release_notes/3.53.0.txt
280
274
  - doc/release_notes/3.6.0.txt
281
275
  - doc/release_notes/3.7.0.txt
282
276
  - doc/release_notes/3.8.0.txt
@@ -288,12 +282,14 @@ files:
288
282
  - lib/roda/plugins/_before_hook.rb
289
283
  - lib/roda/plugins/_optimized_matching.rb
290
284
  - lib/roda/plugins/_symbol_regexp_matchers.rb
285
+ - lib/roda/plugins/additional_view_directories.rb
291
286
  - lib/roda/plugins/all_verbs.rb
292
287
  - lib/roda/plugins/assets.rb
293
288
  - lib/roda/plugins/assets_preloading.rb
294
289
  - lib/roda/plugins/backtracking_array.rb
295
290
  - lib/roda/plugins/branch_locals.rb
296
291
  - lib/roda/plugins/caching.rb
292
+ - lib/roda/plugins/capture_erb.rb
297
293
  - lib/roda/plugins/chunked.rb
298
294
  - lib/roda/plugins/class_level_routing.rb
299
295
  - lib/roda/plugins/class_matchers.rb
@@ -329,6 +325,7 @@ files:
329
325
  - lib/roda/plugins/hooks.rb
330
326
  - lib/roda/plugins/host_authorization.rb
331
327
  - lib/roda/plugins/indifferent_params.rb
328
+ - lib/roda/plugins/inject_erb.rb
332
329
  - lib/roda/plugins/json.rb
333
330
  - lib/roda/plugins/json_parser.rb
334
331
  - lib/roda/plugins/mail_processor.rb
@@ -402,7 +399,7 @@ metadata:
402
399
  bug_tracker_uri: https://github.com/jeremyevans/roda/issues
403
400
  changelog_uri: http://roda.jeremyevans.net/rdoc/files/CHANGELOG.html
404
401
  documentation_uri: http://roda.jeremyevans.net/documentation.html
405
- mailing_list_uri: https://groups.google.com/forum/#!forum/ruby-roda
402
+ mailing_list_uri: https://github.com/jeremyevans/roda/discussions
406
403
  source_code_uri: https://github.com/jeremyevans/roda
407
404
  post_install_message:
408
405
  rdoc_options: []
@@ -419,7 +416,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
419
416
  - !ruby/object:Gem::Version
420
417
  version: '0'
421
418
  requirements: []
422
- rubygems_version: 3.2.22
419
+ rubygems_version: 3.3.3
423
420
  signing_key:
424
421
  specification_version: 4
425
422
  summary: Routing tree web toolkit