actionpack 6.1.7.5 → 7.0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +323 -399
- data/MIT-LICENSE +1 -0
- data/README.rdoc +4 -5
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +13 -26
- data/lib/abstract_controller/caching/fragments.rb +2 -2
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +21 -7
- data/lib/abstract_controller/collector.rb +2 -2
- data/lib/abstract_controller/error.rb +1 -1
- data/lib/abstract_controller/helpers.rb +17 -12
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +9 -11
- data/lib/abstract_controller/translation.rb +27 -4
- data/lib/abstract_controller/url_for.rb +4 -6
- data/lib/action_controller/api.rb +7 -7
- data/lib/action_controller/base.rb +5 -4
- data/lib/action_controller/form_builder.rb +2 -2
- data/lib/action_controller/log_subscriber.rb +4 -3
- data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
- data/lib/action_controller/metal/conditional_get.rb +137 -102
- data/lib/action_controller/metal/content_security_policy.rb +36 -2
- data/lib/action_controller/metal/cookies.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +23 -31
- data/lib/action_controller/metal/etag_with_flash.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +19 -30
- data/lib/action_controller/metal/flash.rb +6 -2
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/http_authentication.rb +66 -39
- data/lib/action_controller/metal/instrumentation.rb +57 -52
- data/lib/action_controller/metal/live.rb +43 -2
- data/lib/action_controller/metal/mime_responds.rb +3 -3
- data/lib/action_controller/metal/params_wrapper.rb +20 -11
- data/lib/action_controller/metal/permissions_policy.rb +19 -28
- data/lib/action_controller/metal/redirecting.rb +95 -22
- data/lib/action_controller/metal/renderers.rb +12 -13
- data/lib/action_controller/metal/rendering.rb +121 -9
- data/lib/action_controller/metal/request_forgery_protection.rb +83 -32
- data/lib/action_controller/metal/rescue.rb +5 -4
- data/lib/action_controller/metal/streaming.rb +7 -9
- data/lib/action_controller/metal/strong_parameters.rb +138 -115
- data/lib/action_controller/metal/testing.rb +9 -2
- data/lib/action_controller/metal/url_for.rb +3 -5
- data/lib/action_controller/metal.rb +10 -13
- data/lib/action_controller/railtie.rb +50 -6
- data/lib/action_controller/renderer.rb +1 -20
- data/lib/action_controller/test_case.rb +28 -7
- data/lib/action_controller.rb +2 -5
- data/lib/action_dispatch/http/cache.rb +20 -13
- data/lib/action_dispatch/http/content_security_policy.rb +113 -36
- data/lib/action_dispatch/http/filter_parameters.rb +4 -19
- data/lib/action_dispatch/http/headers.rb +1 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +15 -5
- data/lib/action_dispatch/http/mime_type.rb +9 -11
- data/lib/action_dispatch/http/parameters.rb +5 -5
- data/lib/action_dispatch/http/permissions_policy.rb +17 -1
- data/lib/action_dispatch/http/request.rb +27 -37
- data/lib/action_dispatch/http/response.rb +3 -20
- data/lib/action_dispatch/http/upload.rb +13 -2
- data/lib/action_dispatch/http/url.rb +11 -19
- data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
- data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
- data/lib/action_dispatch/journey/nodes/node.rb +70 -5
- data/lib/action_dispatch/journey/path/pattern.rb +22 -13
- data/lib/action_dispatch/journey/route.rb +6 -13
- data/lib/action_dispatch/journey/router/utils.rb +2 -2
- data/lib/action_dispatch/journey/router.rb +1 -1
- data/lib/action_dispatch/journey/routes.rb +3 -3
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
- data/lib/action_dispatch/middleware/cookies.rb +20 -13
- data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
- data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
- data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
- data/lib/action_dispatch/middleware/executor.rb +3 -0
- data/lib/action_dispatch/middleware/flash.rb +17 -18
- data/lib/action_dispatch/middleware/host_authorization.rb +13 -17
- data/lib/action_dispatch/middleware/remote_ip.rb +20 -8
- data/lib/action_dispatch/middleware/request_id.rb +3 -3
- data/lib/action_dispatch/middleware/server_timing.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
- data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
- data/lib/action_dispatch/middleware/show_exceptions.rb +17 -16
- data/lib/action_dispatch/middleware/stack.rb +27 -9
- data/lib/action_dispatch/middleware/static.rb +5 -9
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +22 -22
- data/lib/action_dispatch/railtie.rb +8 -2
- data/lib/action_dispatch/request/session.rb +43 -13
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +82 -83
- data/lib/action_dispatch/routing/redirection.rb +5 -2
- data/lib/action_dispatch/routing/route_set.rb +17 -7
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
- data/lib/action_dispatch/routing/url_for.rb +24 -25
- data/lib/action_dispatch/routing.rb +5 -6
- data/lib/action_dispatch/system_test_case.rb +5 -5
- data/lib/action_dispatch/system_testing/browser.rb +3 -13
- data/lib/action_dispatch/system_testing/driver.rb +34 -10
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +11 -7
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
- data/lib/action_dispatch/testing/assertions/response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
- data/lib/action_dispatch/testing/assertions.rb +2 -5
- data/lib/action_dispatch/testing/integration.rb +6 -8
- data/lib/action_dispatch/testing/test_process.rb +3 -29
- data/lib/action_dispatch/testing/test_response.rb +20 -2
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_pack/gem_version.rb +5 -5
- data/lib/action_pack/version.rb +1 -1
- metadata +16 -15
@@ -4,7 +4,6 @@ require "active_support/core_ext/hash/slice"
|
|
4
4
|
require "active_support/core_ext/enumerable"
|
5
5
|
require "active_support/core_ext/array/extract_options"
|
6
6
|
require "active_support/core_ext/regexp"
|
7
|
-
require "active_support/core_ext/symbol/starts_ends_with"
|
8
7
|
require "action_dispatch/routing/redirection"
|
9
8
|
require "action_dispatch/routing/endpoint"
|
10
9
|
|
@@ -13,7 +12,7 @@ module ActionDispatch
|
|
13
12
|
class Mapper
|
14
13
|
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
|
15
14
|
|
16
|
-
class Constraints < Routing::Endpoint
|
15
|
+
class Constraints < Routing::Endpoint # :nodoc:
|
17
16
|
attr_reader :app, :constraints
|
18
17
|
|
19
18
|
SERVE = ->(app, req) { app.serve req }
|
@@ -67,11 +66,11 @@ module ActionDispatch
|
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
70
|
-
class Mapping
|
69
|
+
class Mapping # :nodoc:
|
71
70
|
ANCHOR_CHARACTERS_REGEX = %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
|
72
71
|
OPTIONAL_FORMAT_REGEX = %r{(?:\(\.:format\)+|\.:format|/)\Z}
|
73
72
|
|
74
|
-
attr_reader :requirements, :defaults, :to, :default_controller,
|
73
|
+
attr_reader :path, :requirements, :defaults, :to, :default_controller,
|
75
74
|
:default_action, :required_defaults, :ast, :scope_options
|
76
75
|
|
77
76
|
def self.build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
|
@@ -122,31 +121,17 @@ module ActionDispatch
|
|
122
121
|
@to = intern(to)
|
123
122
|
@default_controller = intern(controller)
|
124
123
|
@default_action = intern(default_action)
|
125
|
-
@ast = ast
|
126
124
|
@anchor = anchor
|
127
125
|
@via = via
|
128
126
|
@internal = options.delete(:internal)
|
129
127
|
@scope_options = scope_params[:options]
|
128
|
+
ast = Journey::Ast.new(ast, formatted)
|
130
129
|
|
131
|
-
|
132
|
-
wildcard_options = {}
|
133
|
-
ast.each do |node|
|
134
|
-
if node.symbol?
|
135
|
-
path_params << node.to_sym
|
136
|
-
elsif formatted != false && node.star?
|
137
|
-
# Add a constraint for wildcard route to make it non-greedy and match the
|
138
|
-
# optional format part of the route by default.
|
139
|
-
wildcard_options[node.name.to_sym] ||= /.+?/
|
140
|
-
elsif node.cat?
|
141
|
-
alter_regex_for_custom_routes(node)
|
142
|
-
end
|
143
|
-
end
|
130
|
+
options = ast.wildcard_options.merge!(options)
|
144
131
|
|
145
|
-
options =
|
132
|
+
options = normalize_options!(options, ast.path_params, scope_params[:module])
|
146
133
|
|
147
|
-
|
148
|
-
|
149
|
-
split_options = constraints(options, path_params)
|
134
|
+
split_options = constraints(options, ast.path_params)
|
150
135
|
|
151
136
|
constraints = scope_params[:constraints].merge Hash[split_options[:constraints] || []]
|
152
137
|
|
@@ -160,8 +145,8 @@ module ActionDispatch
|
|
160
145
|
@blocks = blocks(options_constraints)
|
161
146
|
end
|
162
147
|
|
163
|
-
requirements, conditions = split_constraints path_params, constraints
|
164
|
-
verify_regexp_requirements requirements.
|
148
|
+
requirements, conditions = split_constraints ast.path_params, constraints
|
149
|
+
verify_regexp_requirements requirements, ast.wildcard_options
|
165
150
|
|
166
151
|
formats = normalize_format(formatted)
|
167
152
|
|
@@ -169,13 +154,18 @@ module ActionDispatch
|
|
169
154
|
@conditions = Hash[conditions]
|
170
155
|
@defaults = formats[:defaults].merge(@defaults).merge(normalize_defaults(options))
|
171
156
|
|
172
|
-
if path_params.include?(:action) && !@requirements.key?(:action)
|
157
|
+
if ast.path_params.include?(:action) && !@requirements.key?(:action)
|
173
158
|
@defaults[:action] ||= "index"
|
174
159
|
end
|
175
160
|
|
176
161
|
@required_defaults = (split_options[:required_defaults] || []).map(&:first)
|
162
|
+
|
163
|
+
ast.requirements = @requirements
|
164
|
+
@path = Journey::Path::Pattern.new(ast, @requirements, JOINED_SEPARATORS, @anchor)
|
177
165
|
end
|
178
166
|
|
167
|
+
JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
|
168
|
+
|
179
169
|
def make_route(name, precedence)
|
180
170
|
Journey::Route.new(name: name, app: application, path: path, constraints: conditions,
|
181
171
|
required_defaults: required_defaults, defaults: defaults,
|
@@ -187,12 +177,6 @@ module ActionDispatch
|
|
187
177
|
app(@blocks)
|
188
178
|
end
|
189
179
|
|
190
|
-
JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
|
191
|
-
|
192
|
-
def path
|
193
|
-
Journey::Path::Pattern.new(@ast, requirements, JOINED_SEPARATORS, @anchor)
|
194
|
-
end
|
195
|
-
|
196
180
|
def conditions
|
197
181
|
build_conditions @conditions, @set.request_class
|
198
182
|
end
|
@@ -212,24 +196,6 @@ module ActionDispatch
|
|
212
196
|
private :request_method
|
213
197
|
|
214
198
|
private
|
215
|
-
# Find all the symbol nodes that are adjacent to literal nodes and alter
|
216
|
-
# the regexp so that Journey will partition them into custom routes.
|
217
|
-
def alter_regex_for_custom_routes(node)
|
218
|
-
if node.left.literal? && node.right.symbol?
|
219
|
-
symbol = node.right
|
220
|
-
elsif node.left.literal? && node.right.cat? && node.right.left.symbol?
|
221
|
-
symbol = node.right.left
|
222
|
-
elsif node.left.symbol? && node.right.literal?
|
223
|
-
symbol = node.left
|
224
|
-
elsif node.left.symbol? && node.right.cat? && node.right.left.literal?
|
225
|
-
symbol = node.left
|
226
|
-
end
|
227
|
-
|
228
|
-
if symbol
|
229
|
-
symbol.regexp = /(?:#{Regexp.union(symbol.regexp, '-')})+/
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
199
|
def intern(object)
|
234
200
|
object.is_a?(String) ? -object : object
|
235
201
|
end
|
@@ -280,14 +246,18 @@ module ActionDispatch
|
|
280
246
|
end
|
281
247
|
end
|
282
248
|
|
283
|
-
def verify_regexp_requirements(requirements)
|
284
|
-
requirements.each do |requirement|
|
285
|
-
|
249
|
+
def verify_regexp_requirements(requirements, wildcard_options)
|
250
|
+
requirements.each do |requirement, regex|
|
251
|
+
next unless regex.is_a? Regexp
|
252
|
+
|
253
|
+
if ANCHOR_CHARACTERS_REGEX.match?(regex.source)
|
286
254
|
raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
|
287
255
|
end
|
288
256
|
|
289
|
-
if
|
290
|
-
|
257
|
+
if regex.multiline?
|
258
|
+
next if wildcard_options.key?(requirement)
|
259
|
+
|
260
|
+
raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{regex.inspect}"
|
291
261
|
end
|
292
262
|
end
|
293
263
|
end
|
@@ -420,10 +390,10 @@ module ActionDispatch
|
|
420
390
|
#
|
421
391
|
# If you want to expose your action to both GET and POST, use:
|
422
392
|
#
|
423
|
-
# # sets :controller, :action and :id in params
|
393
|
+
# # sets :controller, :action, and :id in params
|
424
394
|
# match ':controller/:action/:id', via: [:get, :post]
|
425
395
|
#
|
426
|
-
# Note that +:controller+, +:action
|
396
|
+
# Note that +:controller+, +:action+, and +:id+ are interpreted as URL
|
427
397
|
# query parameters and thus available through +params+ in an action.
|
428
398
|
#
|
429
399
|
# If you want to expose your action to GET, use +get+ in the router:
|
@@ -639,7 +609,7 @@ module ActionDispatch
|
|
639
609
|
target_as = name_for_action(options[:as], path)
|
640
610
|
options[:via] ||= :all
|
641
611
|
|
642
|
-
match(path,
|
612
|
+
match(path, { to: app, anchor: false, format: false }.merge(options))
|
643
613
|
|
644
614
|
define_generate_prefix(app, target_as) if rails_app
|
645
615
|
self
|
@@ -936,7 +906,7 @@ module ActionDispatch
|
|
936
906
|
#
|
937
907
|
# === Options
|
938
908
|
#
|
939
|
-
# The +:path+, +:as+, +:module+, +:shallow_path
|
909
|
+
# The +:path+, +:as+, +:module+, +:shallow_path+, and +:shallow_prefix+
|
940
910
|
# options all default to the name of the namespace.
|
941
911
|
#
|
942
912
|
# For options, see <tt>Base#match</tt>. For +:shallow_path+ option, see
|
@@ -956,7 +926,7 @@ module ActionDispatch
|
|
956
926
|
# namespace :admin, as: "sekret" do
|
957
927
|
# resources :posts
|
958
928
|
# end
|
959
|
-
def namespace(path, options = {})
|
929
|
+
def namespace(path, options = {}, &block)
|
960
930
|
path = path.to_s
|
961
931
|
|
962
932
|
defaults = {
|
@@ -967,7 +937,7 @@ module ActionDispatch
|
|
967
937
|
}
|
968
938
|
|
969
939
|
path_scope(options.delete(:path) { path }) do
|
970
|
-
scope(defaults.merge!(options))
|
940
|
+
scope(defaults.merge!(options), &block)
|
971
941
|
end
|
972
942
|
end
|
973
943
|
|
@@ -1026,8 +996,8 @@ module ActionDispatch
|
|
1026
996
|
# constraints(Iphone) do
|
1027
997
|
# resources :iphones
|
1028
998
|
# end
|
1029
|
-
def constraints(constraints = {})
|
1030
|
-
scope(constraints: constraints)
|
999
|
+
def constraints(constraints = {}, &block)
|
1000
|
+
scope(constraints: constraints, &block)
|
1031
1001
|
end
|
1032
1002
|
|
1033
1003
|
# Allows you to set default parameters for a route, such as this:
|
@@ -1112,7 +1082,7 @@ module ActionDispatch
|
|
1112
1082
|
|
1113
1083
|
# Resource routing allows you to quickly declare all of the common routes
|
1114
1084
|
# for a given resourceful controller. Instead of declaring separate routes
|
1115
|
-
# for your +index+, +show+, +new+, +edit+, +create+, +update
|
1085
|
+
# for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
|
1116
1086
|
# actions, a resourceful route declares them in a single line of code:
|
1117
1087
|
#
|
1118
1088
|
# resources :photos
|
@@ -1156,7 +1126,7 @@ module ActionDispatch
|
|
1156
1126
|
RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except, :param, :concerns]
|
1157
1127
|
CANONICAL_ACTIONS = %w(index create new show update destroy)
|
1158
1128
|
|
1159
|
-
class Resource
|
1129
|
+
class Resource # :nodoc:
|
1160
1130
|
attr_reader :controller, :path, :param
|
1161
1131
|
|
1162
1132
|
def initialize(entities, api_only, shallow, options = {})
|
@@ -1251,7 +1221,7 @@ module ActionDispatch
|
|
1251
1221
|
def singleton?; false; end
|
1252
1222
|
end
|
1253
1223
|
|
1254
|
-
class SingletonResource < Resource
|
1224
|
+
class SingletonResource < Resource # :nodoc:
|
1255
1225
|
def initialize(entities, api_only, shallow, options)
|
1256
1226
|
super
|
1257
1227
|
@as = nil
|
@@ -1307,6 +1277,16 @@ module ActionDispatch
|
|
1307
1277
|
# DELETE /profile
|
1308
1278
|
# POST /profile
|
1309
1279
|
#
|
1280
|
+
# If you want instances of a model to work with this resource via
|
1281
|
+
# record identification (e.g. in +form_with+ or +redirect_to+), you
|
1282
|
+
# will need to call resolve[rdoc-ref:CustomUrls#resolve]:
|
1283
|
+
#
|
1284
|
+
# resource :profile
|
1285
|
+
# resolve('Profile') { [:profile] }
|
1286
|
+
#
|
1287
|
+
# # Enables this to work with singular routes:
|
1288
|
+
# form_with(model: @profile) {}
|
1289
|
+
#
|
1310
1290
|
# === Options
|
1311
1291
|
# Takes same options as resources[rdoc-ref:#resources]
|
1312
1292
|
def resource(*resources, &block)
|
@@ -1517,15 +1497,13 @@ module ActionDispatch
|
|
1517
1497
|
# with GET, and route to the search action of +PhotosController+. It will also
|
1518
1498
|
# create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
|
1519
1499
|
# route helpers.
|
1520
|
-
def collection
|
1500
|
+
def collection(&block)
|
1521
1501
|
unless resource_scope?
|
1522
1502
|
raise ArgumentError, "can't use collection outside resource(s) scope"
|
1523
1503
|
end
|
1524
1504
|
|
1525
1505
|
with_scope_level(:collection) do
|
1526
|
-
path_scope(parent_resource.collection_scope)
|
1527
|
-
yield
|
1528
|
-
end
|
1506
|
+
path_scope(parent_resource.collection_scope, &block)
|
1529
1507
|
end
|
1530
1508
|
end
|
1531
1509
|
|
@@ -1540,7 +1518,7 @@ module ActionDispatch
|
|
1540
1518
|
# This will recognize <tt>/photos/1/preview</tt> with GET, and route to the
|
1541
1519
|
# preview action of +PhotosController+. It will also create the
|
1542
1520
|
# <tt>preview_photo_url</tt> and <tt>preview_photo_path</tt> helpers.
|
1543
|
-
def member
|
1521
|
+
def member(&block)
|
1544
1522
|
unless resource_scope?
|
1545
1523
|
raise ArgumentError, "can't use member outside resource(s) scope"
|
1546
1524
|
end
|
@@ -1548,27 +1526,25 @@ module ActionDispatch
|
|
1548
1526
|
with_scope_level(:member) do
|
1549
1527
|
if shallow?
|
1550
1528
|
shallow_scope {
|
1551
|
-
path_scope(parent_resource.member_scope)
|
1529
|
+
path_scope(parent_resource.member_scope, &block)
|
1552
1530
|
}
|
1553
1531
|
else
|
1554
|
-
path_scope(parent_resource.member_scope)
|
1532
|
+
path_scope(parent_resource.member_scope, &block)
|
1555
1533
|
end
|
1556
1534
|
end
|
1557
1535
|
end
|
1558
1536
|
|
1559
|
-
def new
|
1537
|
+
def new(&block)
|
1560
1538
|
unless resource_scope?
|
1561
1539
|
raise ArgumentError, "can't use new outside resource(s) scope"
|
1562
1540
|
end
|
1563
1541
|
|
1564
1542
|
with_scope_level(:new) do
|
1565
|
-
path_scope(parent_resource.new_scope(action_path(:new)))
|
1566
|
-
yield
|
1567
|
-
end
|
1543
|
+
path_scope(parent_resource.new_scope(action_path(:new)), &block)
|
1568
1544
|
end
|
1569
1545
|
end
|
1570
1546
|
|
1571
|
-
def nested
|
1547
|
+
def nested(&block)
|
1572
1548
|
unless resource_scope?
|
1573
1549
|
raise ArgumentError, "can't use nested outside resource(s) scope"
|
1574
1550
|
end
|
@@ -1577,12 +1553,12 @@ module ActionDispatch
|
|
1577
1553
|
if shallow? && shallow_nesting_depth >= 1
|
1578
1554
|
shallow_scope do
|
1579
1555
|
path_scope(parent_resource.nested_scope) do
|
1580
|
-
scope(nested_options)
|
1556
|
+
scope(nested_options, &block)
|
1581
1557
|
end
|
1582
1558
|
end
|
1583
1559
|
else
|
1584
1560
|
path_scope(parent_resource.nested_scope) do
|
1585
|
-
scope(nested_options)
|
1561
|
+
scope(nested_options, &block)
|
1586
1562
|
end
|
1587
1563
|
end
|
1588
1564
|
end
|
@@ -1608,6 +1584,29 @@ module ActionDispatch
|
|
1608
1584
|
!parent_resource.singleton? && @scope[:shallow]
|
1609
1585
|
end
|
1610
1586
|
|
1587
|
+
# Loads another routes file with the given +name+ located inside the
|
1588
|
+
# +config/routes+ directory. In that file, you can use the normal
|
1589
|
+
# routing DSL, but <i>do not</i> surround it with a
|
1590
|
+
# +Rails.application.routes.draw+ block.
|
1591
|
+
#
|
1592
|
+
# # config/routes.rb
|
1593
|
+
# Rails.application.routes.draw do
|
1594
|
+
# draw :admin # Loads `config/routes/admin.rb`
|
1595
|
+
# draw "third_party/some_gem" # Loads `config/routes/third_party/some_gem.rb`
|
1596
|
+
# end
|
1597
|
+
#
|
1598
|
+
# # config/routes/admin.rb
|
1599
|
+
# namespace :admin do
|
1600
|
+
# resources :accounts
|
1601
|
+
# end
|
1602
|
+
#
|
1603
|
+
# # config/routes/third_party/some_gem.rb
|
1604
|
+
# mount SomeGem::Engine, at: "/some_gem"
|
1605
|
+
#
|
1606
|
+
# <b>CAUTION:</b> Use this feature with care. Having multiple routes
|
1607
|
+
# files can negatively impact discoverability and readability. For most
|
1608
|
+
# applications — even those with a few hundred routes — it's easier for
|
1609
|
+
# developers to have a single routes file.
|
1611
1610
|
def draw(name)
|
1612
1611
|
path = @draw_paths.find do |_path|
|
1613
1612
|
File.exist? "#{_path}/#{name}.rb"
|
@@ -1768,10 +1767,10 @@ module ActionDispatch
|
|
1768
1767
|
@scope = @scope.parent
|
1769
1768
|
end
|
1770
1769
|
|
1771
|
-
def resource_scope(resource)
|
1770
|
+
def resource_scope(resource, &block)
|
1772
1771
|
@scope = @scope.new(scope_level_resource: resource)
|
1773
1772
|
|
1774
|
-
controller(resource.resource_scope)
|
1773
|
+
controller(resource.resource_scope, &block)
|
1775
1774
|
ensure
|
1776
1775
|
@scope = @scope.parent
|
1777
1776
|
end
|
@@ -1889,7 +1888,7 @@ module ActionDispatch
|
|
1889
1888
|
end
|
1890
1889
|
|
1891
1890
|
def map_match(paths, options)
|
1892
|
-
if options[:on] && !VALID_ON_OPTIONS.include?(
|
1891
|
+
if (on = options[:on]) && !VALID_ON_OPTIONS.include?(on)
|
1893
1892
|
raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
|
1894
1893
|
end
|
1895
1894
|
|
@@ -2300,7 +2299,7 @@ module ActionDispatch
|
|
2300
2299
|
NULL = Scope.new(nil, nil)
|
2301
2300
|
end
|
2302
2301
|
|
2303
|
-
def initialize(set)
|
2302
|
+
def initialize(set) # :nodoc:
|
2304
2303
|
@set = set
|
2305
2304
|
@draw_paths = set.draw_paths
|
2306
2305
|
@scope = Scope.new(path_names: @set.resources_path_names)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "action_dispatch/http/request"
|
4
|
-
require "active_support/core_ext/uri"
|
5
3
|
require "active_support/core_ext/array/extract_options"
|
6
4
|
require "rack/utils"
|
7
5
|
require "action_controller/metal/exceptions"
|
@@ -144,6 +142,11 @@ module ActionDispatch
|
|
144
142
|
# This will redirect the user, while ignoring certain parts of the request, including query string, etc.
|
145
143
|
# <tt>/stories</tt>, <tt>/stories?foo=bar</tt>, etc all redirect to <tt>/posts</tt>.
|
146
144
|
#
|
145
|
+
# The redirect will use a <tt>301 Moved Permanently</tt> status code by
|
146
|
+
# default. This can be overridden with the +:status+ option:
|
147
|
+
#
|
148
|
+
# get "/stories" => redirect("/posts", status: 307)
|
149
|
+
#
|
147
150
|
# You can also use interpolation in the supplied redirect argument:
|
148
151
|
#
|
149
152
|
# get 'docs/:article', to: redirect('/wiki/%{article}')
|
@@ -6,7 +6,6 @@ require "active_support/core_ext/module/redefine_method"
|
|
6
6
|
require "active_support/core_ext/module/remove_method"
|
7
7
|
require "active_support/core_ext/array/extract_options"
|
8
8
|
require "action_controller/metal/exceptions"
|
9
|
-
require "action_dispatch/http/request"
|
10
9
|
require "action_dispatch/routing/endpoint"
|
11
10
|
|
12
11
|
module ActionDispatch
|
@@ -132,8 +131,8 @@ module ActionDispatch
|
|
132
131
|
alias [] get
|
133
132
|
alias clear clear!
|
134
133
|
|
135
|
-
def each
|
136
|
-
routes.each
|
134
|
+
def each(&block)
|
135
|
+
routes.each(&block)
|
137
136
|
self
|
138
137
|
end
|
139
138
|
|
@@ -197,7 +196,9 @@ module ActionDispatch
|
|
197
196
|
def call(t, method_name, args, inner_options, url_strategy)
|
198
197
|
if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
|
199
198
|
options = t.url_options.merge @options
|
200
|
-
|
199
|
+
path = optimized_helper(args)
|
200
|
+
path << "/" if options[:trailing_slash] && !path.end_with?("/")
|
201
|
+
options[:path] = path
|
201
202
|
|
202
203
|
original_script_name = options.delete(:original_script_name)
|
203
204
|
script_name = t._routes.find_script_name(options)
|
@@ -597,14 +598,14 @@ module ActionDispatch
|
|
597
598
|
if route.segment_keys.include?(:controller)
|
598
599
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
599
600
|
Using a dynamic :controller segment in a route is deprecated and
|
600
|
-
will be removed in Rails 7.
|
601
|
+
will be removed in Rails 7.1.
|
601
602
|
MSG
|
602
603
|
end
|
603
604
|
|
604
605
|
if route.segment_keys.include?(:action)
|
605
606
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
606
607
|
Using a dynamic :action segment in a route is deprecated and
|
607
|
-
will be removed in Rails 7.
|
608
|
+
will be removed in Rails 7.1.
|
608
609
|
MSG
|
609
610
|
end
|
610
611
|
|
@@ -821,10 +822,19 @@ module ActionDispatch
|
|
821
822
|
|
822
823
|
route_with_params = generate(route_name, path_options, recall)
|
823
824
|
path = route_with_params.path(method_name)
|
825
|
+
|
826
|
+
if options[:trailing_slash] && !options[:format] && !path.end_with?("/")
|
827
|
+
path += "/"
|
828
|
+
end
|
829
|
+
|
824
830
|
params = route_with_params.params
|
825
831
|
|
826
832
|
if options.key? :params
|
827
|
-
|
833
|
+
if options[:params]&.respond_to?(:to_hash)
|
834
|
+
params.merge! options[:params]
|
835
|
+
else
|
836
|
+
params[:params] = options[:params]
|
837
|
+
end
|
828
838
|
end
|
829
839
|
|
830
840
|
options[:path] = path
|
@@ -6,16 +6,16 @@ module ActionDispatch
|
|
6
6
|
# is also possible: a URL can be generated from one of your routing definitions.
|
7
7
|
# URL generation functionality is centralized in this module.
|
8
8
|
#
|
9
|
-
# See ActionDispatch::Routing for general information about routing and routes.rb
|
9
|
+
# See ActionDispatch::Routing for general information about routing and <tt>config/routes.rb</tt>.
|
10
10
|
#
|
11
11
|
# <b>Tip:</b> If you need to generate URLs from your models or some other place,
|
12
|
-
# then
|
12
|
+
# then ActionDispatch::Routing::UrlFor is what you're looking for. Read on for
|
13
13
|
# an introduction. In general, this module should not be included on its own,
|
14
|
-
# as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).
|
14
|
+
# as it is usually included by +url_helpers+ (as in <tt>Rails.application.routes.url_helpers</tt>).
|
15
15
|
#
|
16
16
|
# == URL generation from parameters
|
17
17
|
#
|
18
|
-
# As you may know, some functions, such as ActionController::Base#url_for
|
18
|
+
# As you may know, some functions, such as <tt>ActionController::Base#url_for</tt>
|
19
19
|
# and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
|
20
20
|
# of parameters. For example, you've probably had the chance to write code
|
21
21
|
# like this in one of your views:
|
@@ -24,12 +24,12 @@ module ActionDispatch
|
|
24
24
|
# action: 'new', message: 'Welcome!') %>
|
25
25
|
# # => <a href="/users/new?message=Welcome%21">Click here</a>
|
26
26
|
#
|
27
|
-
# link_to
|
28
|
-
# actually use
|
29
|
-
# they use the
|
27
|
+
# +link_to+, and all other functions that require URL generation functionality,
|
28
|
+
# actually use ActionDispatch::Routing::UrlFor under the hood. And in particular,
|
29
|
+
# they use the ActionDispatch::Routing::UrlFor#url_for method. One can generate
|
30
30
|
# the same path as the above example by using the following code:
|
31
31
|
#
|
32
|
-
# include UrlFor
|
32
|
+
# include ActionDispatch::Routing::UrlFor
|
33
33
|
# url_for(controller: 'users',
|
34
34
|
# action: 'new',
|
35
35
|
# message: 'Welcome!',
|
@@ -48,17 +48,17 @@ module ActionDispatch
|
|
48
48
|
# host: 'www.example.com')
|
49
49
|
# # => "http://www.example.com/users/new?message=Welcome%21"
|
50
50
|
#
|
51
|
-
# By default, all controllers and views have access to a special version of url_for
|
52
|
-
# that already knows what the current hostname is. So if you use url_for in your
|
51
|
+
# By default, all controllers and views have access to a special version of +url_for+,
|
52
|
+
# that already knows what the current hostname is. So if you use +url_for+ in your
|
53
53
|
# controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
|
54
54
|
# argument.
|
55
55
|
#
|
56
|
-
# For convenience
|
57
|
-
#
|
58
|
-
#
|
59
|
-
# the +:host+
|
60
|
-
#
|
61
|
-
#
|
56
|
+
# For convenience, mailers also include ActionDispatch::Routing::UrlFor. So
|
57
|
+
# within mailers, you can use url_for. However, mailers cannot access
|
58
|
+
# incoming web requests in order to derive hostname information, so you have
|
59
|
+
# to provide the +:host+ option or set the default host using
|
60
|
+
# +default_url_options+. For more information on url_for in mailers see the
|
61
|
+
# ActionMailer::Base documentation.
|
62
62
|
#
|
63
63
|
#
|
64
64
|
# == URL generation for named routes
|
@@ -70,9 +70,9 @@ module ActionDispatch
|
|
70
70
|
# resources :users
|
71
71
|
#
|
72
72
|
# This generates, among other things, the method <tt>users_path</tt>. By default,
|
73
|
-
# this method is accessible from your controllers, views and mailers. If you need
|
73
|
+
# this method is accessible from your controllers, views, and mailers. If you need
|
74
74
|
# to access this auto-generated method from other places (such as a model), then
|
75
|
-
# you can do that by including Rails.application.routes.url_helpers in your class:
|
75
|
+
# you can do that by including <tt>Rails.application.routes.url_helpers</tt> in your class:
|
76
76
|
#
|
77
77
|
# class User < ActiveRecord::Base
|
78
78
|
# include Rails.application.routes.url_helpers
|
@@ -103,11 +103,10 @@ module ActionDispatch
|
|
103
103
|
include(*_url_for_modules) if respond_to?(:_url_for_modules)
|
104
104
|
end
|
105
105
|
|
106
|
-
def initialize(
|
106
|
+
def initialize(...)
|
107
107
|
@_routes = nil
|
108
108
|
super
|
109
109
|
end
|
110
|
-
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
111
110
|
|
112
111
|
# Hook overridden in controller to add request information
|
113
112
|
# with +default_url_options+. Application logic should not
|
@@ -116,11 +115,11 @@ module ActionDispatch
|
|
116
115
|
default_url_options
|
117
116
|
end
|
118
117
|
|
119
|
-
# Generate a URL based on the options provided, default_url_options and the
|
120
|
-
# routes defined in routes.rb
|
118
|
+
# Generate a URL based on the options provided, +default_url_options+, and the
|
119
|
+
# routes defined in <tt>config/routes.rb</tt>. The following options are supported:
|
121
120
|
#
|
122
121
|
# * <tt>:only_path</tt> - If true, the relative URL is returned. Defaults to +false+.
|
123
|
-
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to
|
122
|
+
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to <tt>"http"</tt>.
|
124
123
|
# * <tt>:host</tt> - Specifies the host the link should be targeted at.
|
125
124
|
# If <tt>:only_path</tt> is false, this option must be
|
126
125
|
# provided either explicitly, or via +default_url_options+.
|
@@ -135,7 +134,7 @@ module ActionDispatch
|
|
135
134
|
# * <tt>:port</tt> - Optionally specify the port to connect to.
|
136
135
|
# * <tt>:anchor</tt> - An anchor name to be appended to the path.
|
137
136
|
# * <tt>:params</tt> - The query parameters to be appended to the path.
|
138
|
-
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
|
137
|
+
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in <tt>"/archive/2009/"</tt>.
|
139
138
|
# * <tt>:script_name</tt> - Specifies application path relative to domain root. If provided, prepends application path.
|
140
139
|
#
|
141
140
|
# Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
|
@@ -155,7 +154,7 @@ module ActionDispatch
|
|
155
154
|
# # => '/myapp/tasks/testing'
|
156
155
|
#
|
157
156
|
# Missing routes keys may be filled in from the current request's parameters
|
158
|
-
# (e.g. +:controller+, +:action+, +:id
|
157
|
+
# (e.g. +:controller+, +:action+, +:id+, and any other parameters that are
|
159
158
|
# placed in the path). Given that the current action has been reached
|
160
159
|
# through <tt>GET /users/1</tt>:
|
161
160
|
#
|
@@ -28,7 +28,7 @@ module ActionDispatch
|
|
28
28
|
#
|
29
29
|
# Resource routing allows you to quickly declare all of the common routes
|
30
30
|
# for a given resourceful controller. Instead of declaring separate routes
|
31
|
-
# for your +index+, +show+, +new+, +edit+, +create+, +update
|
31
|
+
# for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
|
32
32
|
# actions, a resourceful route declares them in a single line of code:
|
33
33
|
#
|
34
34
|
# resources :photos
|
@@ -65,9 +65,8 @@ module ActionDispatch
|
|
65
65
|
# resources :posts, :comments
|
66
66
|
# end
|
67
67
|
#
|
68
|
-
# For more, see
|
69
|
-
#
|
70
|
-
# <tt>Routing::Mapper::Scoping#scope</tt>.
|
68
|
+
# For more, see Routing::Mapper::Resources#resources,
|
69
|
+
# Routing::Mapper::Scoping#namespace, and Routing::Mapper::Scoping#scope.
|
71
70
|
#
|
72
71
|
# == Non-resourceful routes
|
73
72
|
#
|
@@ -255,7 +254,7 @@ module ActionDispatch
|
|
255
254
|
autoload :UrlFor
|
256
255
|
autoload :PolymorphicRoutes
|
257
256
|
|
258
|
-
SEPARATORS = %w( / . ? )
|
259
|
-
HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options]
|
257
|
+
SEPARATORS = %w( / . ? ) # :nodoc:
|
258
|
+
HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] # :nodoc:
|
260
259
|
end
|
261
260
|
end
|