actionpack 4.2.8 → 5.2.4.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +285 -444
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/lib/abstract_controller.rb +12 -5
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +45 -49
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +78 -15
- data/lib/abstract_controller/callbacks.rb +47 -31
- data/lib/abstract_controller/collector.rb +8 -11
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +25 -25
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +4 -2
- data/lib/abstract_controller/rendering.rb +42 -41
- data/lib/abstract_controller/translation.rb +10 -7
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/action_controller.rb +29 -21
- data/lib/action_controller/api.rb +149 -0
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/base.rb +27 -19
- data/lib/action_controller/caching.rb +14 -57
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +10 -15
- data/lib/action_controller/metal.rb +98 -83
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +118 -44
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +3 -3
- data/lib/action_controller/metal/data_streaming.rb +27 -46
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
- data/lib/action_controller/metal/exceptions.rb +8 -14
- data/lib/action_controller/metal/flash.rb +4 -3
- data/lib/action_controller/metal/force_ssl.rb +23 -21
- data/lib/action_controller/metal/head.rb +21 -19
- data/lib/action_controller/metal/helpers.rb +24 -14
- data/lib/action_controller/metal/http_authentication.rb +64 -57
- data/lib/action_controller/metal/implicit_render.rb +62 -8
- data/lib/action_controller/metal/instrumentation.rb +19 -21
- data/lib/action_controller/metal/live.rb +90 -106
- data/lib/action_controller/metal/mime_responds.rb +33 -46
- data/lib/action_controller/metal/parameter_encoding.rb +51 -0
- data/lib/action_controller/metal/params_wrapper.rb +61 -53
- data/lib/action_controller/metal/redirecting.rb +49 -28
- data/lib/action_controller/metal/renderers.rb +87 -44
- data/lib/action_controller/metal/rendering.rb +72 -50
- data/lib/action_controller/metal/request_forgery_protection.rb +203 -92
- data/lib/action_controller/metal/rescue.rb +9 -16
- data/lib/action_controller/metal/streaming.rb +12 -10
- data/lib/action_controller/metal/strong_parameters.rb +582 -165
- data/lib/action_controller/metal/testing.rb +2 -17
- data/lib/action_controller/metal/url_for.rb +19 -10
- data/lib/action_controller/railtie.rb +28 -10
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +117 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +280 -411
- data/lib/action_dispatch.rb +27 -19
- data/lib/action_dispatch/http/cache.rb +93 -47
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +26 -20
- data/lib/action_dispatch/http/filter_redirect.rb +10 -11
- data/lib/action_dispatch/http/headers.rb +55 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +60 -41
- data/lib/action_dispatch/http/mime_type.rb +134 -121
- data/lib/action_dispatch/http/mime_types.rb +20 -6
- data/lib/action_dispatch/http/parameter_filter.rb +25 -11
- data/lib/action_dispatch/http/parameters.rb +98 -39
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +200 -118
- data/lib/action_dispatch/http/response.rb +225 -110
- data/lib/action_dispatch/http/upload.rb +12 -6
- data/lib/action_dispatch/http/url.rb +110 -28
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/journey/formatter.rb +55 -32
- data/lib/action_dispatch/journey/gtg/builder.rb +7 -5
- data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
- data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -16
- data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
- data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
- data/lib/action_dispatch/journey/nfa/simulator.rb +3 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -48
- data/lib/action_dispatch/journey/nodes/node.rb +18 -6
- data/lib/action_dispatch/journey/parser.rb +23 -22
- data/lib/action_dispatch/journey/parser.y +3 -2
- data/lib/action_dispatch/journey/parser_extras.rb +12 -4
- data/lib/action_dispatch/journey/path/pattern.rb +50 -44
- data/lib/action_dispatch/journey/route.rb +106 -28
- data/lib/action_dispatch/journey/router.rb +35 -23
- data/lib/action_dispatch/journey/router/utils.rb +20 -11
- data/lib/action_dispatch/journey/routes.rb +18 -16
- data/lib/action_dispatch/journey/scanner.rb +18 -15
- data/lib/action_dispatch/journey/visitors.rb +99 -52
- data/lib/action_dispatch/middleware/callbacks.rb +1 -2
- data/lib/action_dispatch/middleware/cookies.rb +304 -193
- data/lib/action_dispatch/middleware/debug_exceptions.rb +152 -57
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +68 -69
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +78 -54
- data/lib/action_dispatch/middleware/public_exceptions.rb +27 -25
- data/lib/action_dispatch/middleware/reloader.rb +5 -91
- data/lib/action_dispatch/middleware/remote_ip.rb +41 -31
- data/lib/action_dispatch/middleware/request_id.rb +17 -9
- data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -25
- data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
- data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -67
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +26 -22
- data/lib/action_dispatch/middleware/ssl.rb +114 -36
- data/lib/action_dispatch/middleware/stack.rb +31 -44
- data/lib/action_dispatch/middleware/static.rb +57 -50
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -64
- data/lib/action_dispatch/railtie.rb +19 -11
- data/lib/action_dispatch/request/session.rb +106 -59
- data/lib/action_dispatch/request/utils.rb +67 -24
- data/lib/action_dispatch/routing.rb +17 -18
- data/lib/action_dispatch/routing/endpoint.rb +9 -2
- data/lib/action_dispatch/routing/inspector.rb +58 -67
- data/lib/action_dispatch/routing/mapper.rb +734 -447
- data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -139
- data/lib/action_dispatch/routing/redirection.rb +36 -26
- data/lib/action_dispatch/routing/route_set.rb +321 -291
- data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
- data/lib/action_dispatch/routing/url_for.rb +65 -25
- data/lib/action_dispatch/system_test_case.rb +147 -0
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +59 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +47 -0
- data/lib/action_dispatch/testing/assertions.rb +6 -4
- data/lib/action_dispatch/testing/assertions/response.rb +45 -20
- data/lib/action_dispatch/testing/assertions/routing.rb +30 -26
- data/lib/action_dispatch/testing/integration.rb +347 -209
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +28 -22
- data/lib/action_dispatch/testing/test_request.rb +27 -34
- data/lib/action_dispatch/testing/test_response.rb +35 -7
- data/lib/action_pack.rb +4 -2
- data/lib/action_pack/gem_version.rb +5 -3
- data/lib/action_pack/version.rb +3 -1
- metadata +56 -39
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
module Journey # :nodoc:
|
3
5
|
class Router # :nodoc:
|
@@ -5,7 +7,7 @@ module ActionDispatch
|
|
5
7
|
# Normalizes URI path.
|
6
8
|
#
|
7
9
|
# Strips off trailing slash and ensures there is a leading slash.
|
8
|
-
# Also converts downcase
|
10
|
+
# Also converts downcase URL encoded string to uppercase.
|
9
11
|
#
|
10
12
|
# normalize_path("/foo") # => "/foo"
|
11
13
|
# normalize_path("/foo/") # => "/foo"
|
@@ -13,22 +15,25 @@ module ActionDispatch
|
|
13
15
|
# normalize_path("") # => "/"
|
14
16
|
# normalize_path("/%ab") # => "/%AB"
|
15
17
|
def self.normalize_path(path)
|
16
|
-
path
|
17
|
-
path.
|
18
|
-
path
|
18
|
+
path ||= ""
|
19
|
+
encoding = path.encoding
|
20
|
+
path = "/#{path}".dup
|
21
|
+
path.squeeze!("/".freeze)
|
22
|
+
path.sub!(%r{/+\Z}, "".freeze)
|
19
23
|
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
|
20
|
-
path =
|
24
|
+
path = "/".dup if path == "".freeze
|
25
|
+
path.force_encoding(encoding)
|
21
26
|
path
|
22
27
|
end
|
23
28
|
|
24
29
|
# URI path and fragment escaping
|
25
|
-
#
|
30
|
+
# https://tools.ietf.org/html/rfc3986
|
26
31
|
class UriEncoder # :nodoc:
|
27
32
|
ENCODE = "%%%02X".freeze
|
28
33
|
US_ASCII = Encoding::US_ASCII
|
29
34
|
UTF_8 = Encoding::UTF_8
|
30
|
-
EMPTY = "".force_encoding(US_ASCII).freeze
|
31
|
-
DEC2HEX = (0..255).to_a.map{ |i| ENCODE % i }.map{ |s| s.force_encoding(US_ASCII) }
|
35
|
+
EMPTY = "".dup.force_encoding(US_ASCII).freeze
|
36
|
+
DEC2HEX = (0..255).to_a.map { |i| ENCODE % i }.map { |s| s.force_encoding(US_ASCII) }
|
32
37
|
|
33
38
|
ALPHA = "a-zA-Z".freeze
|
34
39
|
DIGIT = "0-9".freeze
|
@@ -55,12 +60,12 @@ module ActionDispatch
|
|
55
60
|
|
56
61
|
def unescape_uri(uri)
|
57
62
|
encoding = uri.encoding == US_ASCII ? UTF_8 : uri.encoding
|
58
|
-
uri.gsub(ESCAPED) { [
|
63
|
+
uri.gsub(ESCAPED) { |match| [match[1, 2].hex].pack("C") }.force_encoding(encoding)
|
59
64
|
end
|
60
65
|
|
61
|
-
|
66
|
+
private
|
62
67
|
def escape(component, pattern)
|
63
|
-
component.gsub(pattern){ |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
|
68
|
+
component.gsub(pattern) { |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
|
64
69
|
end
|
65
70
|
|
66
71
|
def percent_encode(unsafe)
|
@@ -84,6 +89,10 @@ module ActionDispatch
|
|
84
89
|
ENCODER.escape_fragment(fragment.to_s)
|
85
90
|
end
|
86
91
|
|
92
|
+
# Replaces any escaped sequences with their unescaped representations.
|
93
|
+
#
|
94
|
+
# uri = "/topics?title=Ruby%20on%20Rails"
|
95
|
+
# unescape_uri(uri) #=> "/topics?title=Ruby on Rails"
|
87
96
|
def self.unescape_uri(uri)
|
88
97
|
ENCODER.unescape_uri(uri)
|
89
98
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
module Journey # :nodoc:
|
3
5
|
# The Routing table. Contains all routes for a system. Routes can be
|
@@ -5,13 +7,13 @@ module ActionDispatch
|
|
5
7
|
class Routes # :nodoc:
|
6
8
|
include Enumerable
|
7
9
|
|
8
|
-
attr_reader :routes, :
|
10
|
+
attr_reader :routes, :custom_routes, :anchored_routes
|
9
11
|
|
10
12
|
def initialize
|
11
13
|
@routes = []
|
12
|
-
@named_routes = {}
|
13
14
|
@ast = nil
|
14
|
-
@
|
15
|
+
@anchored_routes = []
|
16
|
+
@custom_routes = []
|
15
17
|
@simulator = nil
|
16
18
|
end
|
17
19
|
|
@@ -34,36 +36,37 @@ module ActionDispatch
|
|
34
36
|
|
35
37
|
def clear
|
36
38
|
routes.clear
|
37
|
-
|
39
|
+
anchored_routes.clear
|
40
|
+
custom_routes.clear
|
38
41
|
end
|
39
42
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
+
def partition_route(route)
|
44
|
+
if route.path.anchored && route.ast.grep(Nodes::Symbol).all?(&:default_regexp?)
|
45
|
+
anchored_routes << route
|
46
|
+
else
|
47
|
+
custom_routes << route
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
46
51
|
def ast
|
47
52
|
@ast ||= begin
|
48
|
-
asts =
|
49
|
-
Nodes::Or.new(asts)
|
53
|
+
asts = anchored_routes.map(&:ast)
|
54
|
+
Nodes::Or.new(asts)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
53
58
|
def simulator
|
59
|
+
return if ast.nil?
|
54
60
|
@simulator ||= begin
|
55
61
|
gtg = GTG::Builder.new(ast).transition_table
|
56
62
|
GTG::Simulator.new(gtg)
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
route = Route.new(name, app, path, conditions, defaults)
|
63
|
-
|
64
|
-
route.precedence = routes.length
|
66
|
+
def add_route(name, mapping)
|
67
|
+
route = mapping.make_route name, routes.length
|
65
68
|
routes << route
|
66
|
-
|
69
|
+
partition_route(route)
|
67
70
|
clear_cache!
|
68
71
|
route
|
69
72
|
end
|
@@ -72,7 +75,6 @@ module ActionDispatch
|
|
72
75
|
|
73
76
|
def clear_cache!
|
74
77
|
@ast = nil
|
75
|
-
@partitioned_routes = nil
|
76
78
|
@simulator = nil
|
77
79
|
end
|
78
80
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "strscan"
|
2
4
|
|
3
5
|
module ActionDispatch
|
4
6
|
module Journey # :nodoc:
|
@@ -35,22 +37,23 @@ module ActionDispatch
|
|
35
37
|
def scan
|
36
38
|
case
|
37
39
|
# /
|
38
|
-
when
|
39
|
-
[:SLASH,
|
40
|
+
when @ss.skip(/\//)
|
41
|
+
[:SLASH, "/"]
|
42
|
+
when @ss.skip(/\(/)
|
43
|
+
[:LPAREN, "("]
|
44
|
+
when @ss.skip(/\)/)
|
45
|
+
[:RPAREN, ")"]
|
46
|
+
when @ss.skip(/\|/)
|
47
|
+
[:OR, "|"]
|
48
|
+
when @ss.skip(/\./)
|
49
|
+
[:DOT, "."]
|
50
|
+
when text = @ss.scan(/:\w+/)
|
51
|
+
[:SYMBOL, text]
|
40
52
|
when text = @ss.scan(/\*\w+/)
|
41
53
|
[:STAR, text]
|
42
|
-
when text = @ss.scan(/(
|
43
|
-
|
44
|
-
|
45
|
-
[:RPAREN, text]
|
46
|
-
when text = @ss.scan(/\|/)
|
47
|
-
[:OR, text]
|
48
|
-
when text = @ss.scan(/\./)
|
49
|
-
[:DOT, text]
|
50
|
-
when text = @ss.scan(/(?<!\\):\w+/)
|
51
|
-
[:SYMBOL, text]
|
52
|
-
when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\:|\\\(|\\\))+/)
|
53
|
-
[:LITERAL, text.tr('\\', '')]
|
54
|
+
when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/)
|
55
|
+
text.tr! "\\", ""
|
56
|
+
[:LITERAL, text]
|
54
57
|
# any char
|
55
58
|
when text = @ss.scan(/./)
|
56
59
|
[:LITERAL, text]
|
@@ -1,12 +1,13 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
|
-
|
4
|
+
# :stopdoc:
|
5
|
+
module Journey
|
5
6
|
class Format
|
6
7
|
ESCAPE_PATH = ->(value) { Router::Utils.escape_path(value) }
|
7
8
|
ESCAPE_SEGMENT = ->(value) { Router::Utils.escape_segment(value) }
|
8
9
|
|
9
|
-
|
10
|
+
Parameter = Struct.new(:name, :escaper) do
|
10
11
|
def escape(value); escaper.call value; end
|
11
12
|
end
|
12
13
|
|
@@ -23,7 +24,7 @@ module ActionDispatch
|
|
23
24
|
@children = []
|
24
25
|
@parameters = []
|
25
26
|
|
26
|
-
parts.each_with_index do |object,i|
|
27
|
+
parts.each_with_index do |object, i|
|
27
28
|
case object
|
28
29
|
when Journey::Format
|
29
30
|
@children << i
|
@@ -39,7 +40,7 @@ module ActionDispatch
|
|
39
40
|
@parameters.each do |index|
|
40
41
|
param = parts[index]
|
41
42
|
value = hash[param.name]
|
42
|
-
return
|
43
|
+
return "".freeze unless value
|
43
44
|
parts[index] = param.escape value
|
44
45
|
end
|
45
46
|
|
@@ -59,7 +60,7 @@ module ActionDispatch
|
|
59
60
|
|
60
61
|
private
|
61
62
|
|
62
|
-
def visit
|
63
|
+
def visit(node)
|
63
64
|
send(DISPATCH_CACHE[node.type], node)
|
64
65
|
end
|
65
66
|
|
@@ -92,6 +93,45 @@ module ActionDispatch
|
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
96
|
+
class FunctionalVisitor # :nodoc:
|
97
|
+
DISPATCH_CACHE = {}
|
98
|
+
|
99
|
+
def accept(node, seed)
|
100
|
+
visit(node, seed)
|
101
|
+
end
|
102
|
+
|
103
|
+
def visit(node, seed)
|
104
|
+
send(DISPATCH_CACHE[node.type], node, seed)
|
105
|
+
end
|
106
|
+
|
107
|
+
def binary(node, seed)
|
108
|
+
visit(node.right, visit(node.left, seed))
|
109
|
+
end
|
110
|
+
def visit_CAT(n, seed); binary(n, seed); end
|
111
|
+
|
112
|
+
def nary(node, seed)
|
113
|
+
node.children.inject(seed) { |s, c| visit(c, s) }
|
114
|
+
end
|
115
|
+
def visit_OR(n, seed); nary(n, seed); end
|
116
|
+
|
117
|
+
def unary(node, seed)
|
118
|
+
visit(node.left, seed)
|
119
|
+
end
|
120
|
+
def visit_GROUP(n, seed); unary(n, seed); end
|
121
|
+
def visit_STAR(n, seed); unary(n, seed); end
|
122
|
+
|
123
|
+
def terminal(node, seed); seed; end
|
124
|
+
def visit_LITERAL(n, seed); terminal(n, seed); end
|
125
|
+
def visit_SYMBOL(n, seed); terminal(n, seed); end
|
126
|
+
def visit_SLASH(n, seed); terminal(n, seed); end
|
127
|
+
def visit_DOT(n, seed); terminal(n, seed); end
|
128
|
+
|
129
|
+
instance_methods(false).each do |pim|
|
130
|
+
next unless pim =~ /^visit_(.*)$/
|
131
|
+
DISPATCH_CACHE[$1.to_sym] = pim
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
95
135
|
class FormatBuilder < Visitor # :nodoc:
|
96
136
|
def accept(node); Journey::Format.new(super); end
|
97
137
|
def terminal(node); [node.left]; end
|
@@ -116,106 +156,113 @@ module ActionDispatch
|
|
116
156
|
end
|
117
157
|
end
|
118
158
|
|
119
|
-
# Loop through the requirements AST
|
120
|
-
class Each <
|
121
|
-
|
122
|
-
|
123
|
-
def initialize(block)
|
124
|
-
@block = block
|
125
|
-
end
|
126
|
-
|
127
|
-
def visit(node)
|
159
|
+
# Loop through the requirements AST.
|
160
|
+
class Each < FunctionalVisitor # :nodoc:
|
161
|
+
def visit(node, block)
|
128
162
|
block.call(node)
|
129
163
|
super
|
130
164
|
end
|
165
|
+
|
166
|
+
INSTANCE = new
|
131
167
|
end
|
132
168
|
|
133
|
-
class String <
|
169
|
+
class String < FunctionalVisitor # :nodoc:
|
134
170
|
private
|
135
171
|
|
136
|
-
|
137
|
-
|
138
|
-
|
172
|
+
def binary(node, seed)
|
173
|
+
visit(node.right, visit(node.left, seed))
|
174
|
+
end
|
139
175
|
|
140
|
-
|
141
|
-
|
142
|
-
|
176
|
+
def nary(node, seed)
|
177
|
+
last_child = node.children.last
|
178
|
+
node.children.inject(seed) { |s, c|
|
179
|
+
string = visit(c, s)
|
180
|
+
string << "|" unless last_child == c
|
181
|
+
string
|
182
|
+
}
|
183
|
+
end
|
143
184
|
|
144
|
-
|
145
|
-
|
146
|
-
|
185
|
+
def terminal(node, seed)
|
186
|
+
seed + node.left
|
187
|
+
end
|
147
188
|
|
148
|
-
|
149
|
-
|
150
|
-
|
189
|
+
def visit_GROUP(node, seed)
|
190
|
+
visit(node.left, seed.dup << "(") << ")"
|
191
|
+
end
|
192
|
+
|
193
|
+
INSTANCE = new
|
151
194
|
end
|
152
195
|
|
153
|
-
class Dot <
|
196
|
+
class Dot < FunctionalVisitor # :nodoc:
|
154
197
|
def initialize
|
155
198
|
@nodes = []
|
156
199
|
@edges = []
|
157
200
|
end
|
158
201
|
|
159
|
-
def accept(node)
|
202
|
+
def accept(node, seed = [[], []])
|
160
203
|
super
|
204
|
+
nodes, edges = seed
|
161
205
|
<<-eodot
|
162
206
|
digraph parse_tree {
|
163
207
|
size="8,5"
|
164
208
|
node [shape = none];
|
165
209
|
edge [dir = none];
|
166
|
-
#{
|
167
|
-
#{
|
210
|
+
#{nodes.join "\n"}
|
211
|
+
#{edges.join("\n")}
|
168
212
|
}
|
169
213
|
eodot
|
170
214
|
end
|
171
215
|
|
172
216
|
private
|
173
217
|
|
174
|
-
def binary(node)
|
175
|
-
node.children.
|
176
|
-
|
177
|
-
|
218
|
+
def binary(node, seed)
|
219
|
+
seed.last.concat node.children.map { |c|
|
220
|
+
"#{node.object_id} -> #{c.object_id};"
|
221
|
+
}
|
178
222
|
super
|
179
223
|
end
|
180
224
|
|
181
|
-
def nary(node)
|
182
|
-
node.children.
|
183
|
-
|
184
|
-
|
225
|
+
def nary(node, seed)
|
226
|
+
seed.last.concat node.children.map { |c|
|
227
|
+
"#{node.object_id} -> #{c.object_id};"
|
228
|
+
}
|
185
229
|
super
|
186
230
|
end
|
187
231
|
|
188
|
-
def unary(node)
|
189
|
-
|
232
|
+
def unary(node, seed)
|
233
|
+
seed.last << "#{node.object_id} -> #{node.left.object_id};"
|
190
234
|
super
|
191
235
|
end
|
192
236
|
|
193
|
-
def visit_GROUP(node)
|
194
|
-
|
237
|
+
def visit_GROUP(node, seed)
|
238
|
+
seed.first << "#{node.object_id} [label=\"()\"];"
|
195
239
|
super
|
196
240
|
end
|
197
241
|
|
198
|
-
def visit_CAT(node)
|
199
|
-
|
242
|
+
def visit_CAT(node, seed)
|
243
|
+
seed.first << "#{node.object_id} [label=\"○\"];"
|
200
244
|
super
|
201
245
|
end
|
202
246
|
|
203
|
-
def visit_STAR(node)
|
204
|
-
|
247
|
+
def visit_STAR(node, seed)
|
248
|
+
seed.first << "#{node.object_id} [label=\"*\"];"
|
205
249
|
super
|
206
250
|
end
|
207
251
|
|
208
|
-
def visit_OR(node)
|
209
|
-
|
252
|
+
def visit_OR(node, seed)
|
253
|
+
seed.first << "#{node.object_id} [label=\"|\"];"
|
210
254
|
super
|
211
255
|
end
|
212
256
|
|
213
|
-
def terminal(node)
|
257
|
+
def terminal(node, seed)
|
214
258
|
value = node.left
|
215
259
|
|
216
|
-
|
260
|
+
seed.first << "#{node.object_id} [label=\"#{value}\"];"
|
261
|
+
seed
|
217
262
|
end
|
263
|
+
INSTANCE = new
|
218
264
|
end
|
219
265
|
end
|
220
266
|
end
|
267
|
+
# :startdoc:
|
221
268
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module ActionDispatch
|
3
4
|
# Provides callbacks to be executed before and after dispatching the request.
|
@@ -7,8 +8,6 @@ module ActionDispatch
|
|
7
8
|
define_callbacks :call
|
8
9
|
|
9
10
|
class << self
|
10
|
-
delegate :to_prepare, :to_cleanup, :to => "ActionDispatch::Reloader"
|
11
|
-
|
12
11
|
def before(*args, &block)
|
13
12
|
set_callback(:call, :before, *args, &block)
|
14
13
|
end
|