actionpack 6.1.7.3 → 7.0.8
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 +4 -4
- data/CHANGELOG.md +320 -390
- 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 +5 -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 +111 -19
- 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
|