actionpack 7.1.3.4 → 7.2.0.beta1

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.

Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -541
  3. data/lib/abstract_controller/asset_paths.rb +2 -0
  4. data/lib/abstract_controller/base.rb +102 -98
  5. data/lib/abstract_controller/caching/fragments.rb +50 -53
  6. data/lib/abstract_controller/caching.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +66 -64
  8. data/lib/abstract_controller/collector.rb +6 -6
  9. data/lib/abstract_controller/deprecator.rb +2 -0
  10. data/lib/abstract_controller/error.rb +2 -0
  11. data/lib/abstract_controller/helpers.rb +70 -85
  12. data/lib/abstract_controller/logger.rb +2 -0
  13. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  14. data/lib/abstract_controller/rendering.rb +13 -12
  15. data/lib/abstract_controller/translation.rb +11 -10
  16. data/lib/abstract_controller/url_for.rb +8 -6
  17. data/lib/abstract_controller.rb +2 -0
  18. data/lib/action_controller/api/api_rendering.rb +2 -0
  19. data/lib/action_controller/api.rb +74 -72
  20. data/lib/action_controller/base.rb +155 -117
  21. data/lib/action_controller/caching.rb +15 -12
  22. data/lib/action_controller/deprecator.rb +2 -0
  23. data/lib/action_controller/form_builder.rb +20 -17
  24. data/lib/action_controller/log_subscriber.rb +3 -1
  25. data/lib/action_controller/metal/allow_browser.rb +119 -0
  26. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  27. data/lib/action_controller/metal/conditional_get.rb +188 -174
  28. data/lib/action_controller/metal/content_security_policy.rb +25 -24
  29. data/lib/action_controller/metal/cookies.rb +4 -2
  30. data/lib/action_controller/metal/data_streaming.rb +64 -55
  31. data/lib/action_controller/metal/default_headers.rb +5 -3
  32. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
  34. data/lib/action_controller/metal/exceptions.rb +11 -9
  35. data/lib/action_controller/metal/flash.rb +12 -10
  36. data/lib/action_controller/metal/head.rb +12 -10
  37. data/lib/action_controller/metal/helpers.rb +63 -55
  38. data/lib/action_controller/metal/http_authentication.rb +209 -201
  39. data/lib/action_controller/metal/implicit_render.rb +17 -15
  40. data/lib/action_controller/metal/instrumentation.rb +15 -12
  41. data/lib/action_controller/metal/live.rb +113 -107
  42. data/lib/action_controller/metal/logging.rb +6 -4
  43. data/lib/action_controller/metal/mime_responds.rb +151 -142
  44. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  45. data/lib/action_controller/metal/params_wrapper.rb +57 -59
  46. data/lib/action_controller/metal/permissions_policy.rb +13 -12
  47. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  48. data/lib/action_controller/metal/redirecting.rb +108 -82
  49. data/lib/action_controller/metal/renderers.rb +50 -49
  50. data/lib/action_controller/metal/rendering.rb +103 -75
  51. data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
  52. data/lib/action_controller/metal/rescue.rb +11 -9
  53. data/lib/action_controller/metal/streaming.rb +138 -136
  54. data/lib/action_controller/metal/strong_parameters.rb +525 -480
  55. data/lib/action_controller/metal/testing.rb +2 -0
  56. data/lib/action_controller/metal/url_for.rb +17 -15
  57. data/lib/action_controller/metal.rb +58 -57
  58. data/lib/action_controller/railtie.rb +3 -0
  59. data/lib/action_controller/railties/helpers.rb +2 -0
  60. data/lib/action_controller/renderer.rb +42 -36
  61. data/lib/action_controller/template_assertions.rb +4 -2
  62. data/lib/action_controller/test_case.rb +146 -126
  63. data/lib/action_controller.rb +10 -3
  64. data/lib/action_dispatch/constants.rb +2 -0
  65. data/lib/action_dispatch/deprecator.rb +2 -0
  66. data/lib/action_dispatch/http/cache.rb +27 -26
  67. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  68. data/lib/action_dispatch/http/content_security_policy.rb +44 -38
  69. data/lib/action_dispatch/http/filter_parameters.rb +9 -5
  70. data/lib/action_dispatch/http/filter_redirect.rb +15 -1
  71. data/lib/action_dispatch/http/headers.rb +22 -22
  72. data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
  73. data/lib/action_dispatch/http/mime_type.rb +29 -22
  74. data/lib/action_dispatch/http/mime_types.rb +2 -0
  75. data/lib/action_dispatch/http/parameters.rb +11 -9
  76. data/lib/action_dispatch/http/permissions_policy.rb +27 -37
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +71 -71
  79. data/lib/action_dispatch/http/response.rb +61 -61
  80. data/lib/action_dispatch/http/upload.rb +18 -16
  81. data/lib/action_dispatch/http/url.rb +75 -73
  82. data/lib/action_dispatch/journey/formatter.rb +13 -6
  83. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  84. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  85. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  86. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  87. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  88. data/lib/action_dispatch/journey/parser.rb +4 -3
  89. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  90. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  91. data/lib/action_dispatch/journey/route.rb +9 -7
  92. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  93. data/lib/action_dispatch/journey/router.rb +4 -2
  94. data/lib/action_dispatch/journey/routes.rb +4 -2
  95. data/lib/action_dispatch/journey/scanner.rb +4 -2
  96. data/lib/action_dispatch/journey/visitors.rb +2 -0
  97. data/lib/action_dispatch/journey.rb +2 -0
  98. data/lib/action_dispatch/log_subscriber.rb +2 -0
  99. data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
  100. data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
  101. data/lib/action_dispatch/middleware/callbacks.rb +3 -1
  102. data/lib/action_dispatch/middleware/cookies.rb +119 -104
  103. data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
  104. data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
  105. data/lib/action_dispatch/middleware/debug_view.rb +2 -0
  106. data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
  107. data/lib/action_dispatch/middleware/executor.rb +8 -0
  108. data/lib/action_dispatch/middleware/flash.rb +63 -51
  109. data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
  110. data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
  111. data/lib/action_dispatch/middleware/reloader.rb +5 -3
  112. data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
  113. data/lib/action_dispatch/middleware/request_id.rb +14 -9
  114. data/lib/action_dispatch/middleware/server_timing.rb +4 -2
  115. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
  116. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
  117. data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
  118. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
  119. data/lib/action_dispatch/middleware/show_exceptions.rb +31 -21
  120. data/lib/action_dispatch/middleware/ssl.rb +43 -40
  121. data/lib/action_dispatch/middleware/stack.rb +11 -10
  122. data/lib/action_dispatch/middleware/static.rb +33 -31
  123. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
  124. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -1
  125. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
  126. data/lib/action_dispatch/railtie.rb +2 -4
  127. data/lib/action_dispatch/request/session.rb +23 -21
  128. data/lib/action_dispatch/request/utils.rb +2 -0
  129. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  130. data/lib/action_dispatch/routing/inspector.rb +5 -3
  131. data/lib/action_dispatch/routing/mapper.rb +670 -635
  132. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  133. data/lib/action_dispatch/routing/redirection.rb +37 -32
  134. data/lib/action_dispatch/routing/route_set.rb +59 -45
  135. data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
  136. data/lib/action_dispatch/routing/url_for.rb +130 -125
  137. data/lib/action_dispatch/routing.rb +150 -148
  138. data/lib/action_dispatch/system_test_case.rb +91 -81
  139. data/lib/action_dispatch/system_testing/browser.rb +10 -3
  140. data/lib/action_dispatch/system_testing/driver.rb +3 -1
  141. data/lib/action_dispatch/system_testing/server.rb +2 -0
  142. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
  143. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  144. data/lib/action_dispatch/testing/assertion_response.rb +8 -6
  145. data/lib/action_dispatch/testing/assertions/response.rb +26 -23
  146. data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
  147. data/lib/action_dispatch/testing/assertions.rb +2 -0
  148. data/lib/action_dispatch/testing/integration.rb +223 -222
  149. data/lib/action_dispatch/testing/request_encoder.rb +2 -0
  150. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  151. data/lib/action_dispatch/testing/test_process.rb +12 -8
  152. data/lib/action_dispatch/testing/test_request.rb +3 -1
  153. data/lib/action_dispatch/testing/test_response.rb +27 -26
  154. data/lib/action_dispatch.rb +22 -28
  155. data/lib/action_pack/gem_version.rb +6 -4
  156. data/lib/action_pack/version.rb +3 -1
  157. data/lib/action_pack.rb +17 -16
  158. metadata +30 -13
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/hash/slice"
4
6
  require "active_support/core_ext/enumerable"
5
7
  require "active_support/core_ext/array/extract_options"
@@ -10,10 +12,19 @@ require "action_dispatch/routing/endpoint"
10
12
  module ActionDispatch
11
13
  module Routing
12
14
  class Mapper
15
+ class BacktraceCleaner < ActiveSupport::BacktraceCleaner # :nodoc:
16
+ def initialize
17
+ super
18
+ remove_silencers!
19
+ add_core_silencer
20
+ add_stdlib_silencer
21
+ end
22
+ end
23
+
13
24
  URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
14
25
 
15
26
  cattr_accessor :route_source_locations, instance_accessor: false, default: false
16
- cattr_accessor :backtrace_cleaner, instance_accessor: false, default: ActiveSupport::BacktraceCleaner.new
27
+ cattr_accessor :backtrace_cleaner, instance_accessor: false, default: BacktraceCleaner.new
17
28
 
18
29
  class Constraints < Routing::Endpoint # :nodoc:
19
30
  attr_reader :app, :constraints
@@ -22,10 +33,10 @@ module ActionDispatch
22
33
  CALL = ->(app, req) { app.call req.env }
23
34
 
24
35
  def initialize(app, constraints, strategy)
25
- # Unwrap Constraints objects. I don't actually think it's possible
26
- # to pass a Constraints object to this constructor, but there were
27
- # multiple places that kept testing children of this object. I
28
- # *think* they were just being defensive, but I have no idea.
36
+ # Unwrap Constraints objects. I don't actually think it's possible to pass a
37
+ # Constraints object to this constructor, but there were multiple places that
38
+ # kept testing children of this object. I **think** they were just being
39
+ # defensive, but I have no idea.
29
40
  if app.is_a?(self.class)
30
41
  constraints += app.constraints
31
42
  app = app.app
@@ -210,7 +221,7 @@ module ActionDispatch
210
221
  # Add a default constraint for :controller path segments that matches namespaced
211
222
  # controllers with default routes like :controller/:action/:id(.:format), e.g:
212
223
  # GET /admin/products/show/1
213
- # => { controller: 'admin/products', action: 'show', id: '1' }
224
+ # # > { controller: 'admin/products', action: 'show', id: '1' }
214
225
  options[:controller] ||= /.+?/
215
226
  end
216
227
 
@@ -220,12 +231,17 @@ module ActionDispatch
220
231
  if to.nil?
221
232
  controller = default_controller
222
233
  action = default_action
223
- elsif to.is_a?(String) && to.include?("#")
224
- to_endpoint = to.split("#").map!(&:-@)
225
- controller = to_endpoint[0]
226
- action = to_endpoint[1]
234
+ elsif to.is_a?(String)
235
+ if to.include?("#")
236
+ to_endpoint = to.split("#").map!(&:-@)
237
+ controller = to_endpoint[0]
238
+ action = to_endpoint[1]
239
+ else
240
+ controller = default_controller
241
+ action = to
242
+ end
227
243
  else
228
- raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#'"
244
+ raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#', or the controller should be implicit"
229
245
  end
230
246
 
231
247
  controller = add_controller_module(controller, modyoule)
@@ -359,32 +375,53 @@ module ActionDispatch
359
375
  Routing::RouteSet::Dispatcher.new raise_on_name_error
360
376
  end
361
377
 
362
- def route_source_location
363
- if Mapper.route_source_locations
364
- action_dispatch_dir = File.expand_path("..", __dir__)
365
- caller_location = caller_locations.find { |location| !location.path.include?(action_dispatch_dir) }
366
- cleaned_path = Mapper.backtrace_cleaner.clean([caller_location.path]).first
367
- "#{cleaned_path}:#{caller_location.lineno}" if cleaned_path
378
+ if Thread.respond_to?(:each_caller_location)
379
+ def route_source_location
380
+ if Mapper.route_source_locations
381
+ action_dispatch_dir = File.expand_path("..", __dir__)
382
+ Thread.each_caller_location do |location|
383
+ next if location.path.start_with?(action_dispatch_dir)
384
+
385
+ cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
386
+ next if cleaned_path.nil?
387
+
388
+ return "#{cleaned_path}:#{location.lineno}"
389
+ end
390
+ nil
391
+ end
392
+ end
393
+ else
394
+ def route_source_location
395
+ if Mapper.route_source_locations
396
+ action_dispatch_dir = File.expand_path("..", __dir__)
397
+ caller_locations.each do |location|
398
+ next if location.path.start_with?(action_dispatch_dir)
399
+
400
+ cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
401
+ next if cleaned_path.nil?
402
+
403
+ return "#{cleaned_path}:#{location.lineno}"
404
+ end
405
+ nil
406
+ end
368
407
  end
369
408
  end
370
409
  end
371
410
 
372
- # Invokes Journey::Router::Utils.normalize_path, then ensures that
373
- # /(:locale) becomes (/:locale). Except for root cases, where the
374
- # former is the correct one.
411
+ # Invokes Journey::Router::Utils.normalize_path, then ensures that /(:locale)
412
+ # becomes (/:locale). Except for root cases, where the former is the correct
413
+ # one.
375
414
  def self.normalize_path(path)
376
415
  path = Journey::Router::Utils.normalize_path(path)
377
416
 
378
417
  # the path for a root URL at this point can be something like
379
418
  # "/(/:locale)(/:platform)/(:browser)", and we would want
380
- # "/(:locale)(/:platform)(/:browser)"
381
-
382
- # reverse "/(", "/((" etc to "(/", "((/" etc
419
+ # "/(:locale)(/:platform)(/:browser)" reverse "/(", "/((" etc to "(/", "((/" etc
383
420
  path.gsub!(%r{/(\(+)/?}, '\1/')
384
- # if a path is all optional segments, change the leading "(/" back to
385
- # "/(" so it evaluates to "/" when interpreted with no options.
386
- # Unless, however, at least one secondary segment consists of a static
387
- # part, ex. "(/:locale)(/pages/:page)"
421
+ # if a path is all optional segments, change the leading "(/" back to "/(" so it
422
+ # evaluates to "/" when interpreted with no options. Unless, however, at least
423
+ # one secondary segment consists of a static part, ex.
424
+ # "(/:locale)(/pages/:page)"
388
425
  path.sub!(%r{^(\(+)/}, '/\1') if %r{^(\(+[^)]+\))(\(+/:[^)]+\))*$}.match?(path)
389
426
  path
390
427
  end
@@ -396,206 +433,202 @@ module ActionDispatch
396
433
  module Base
397
434
  # Matches a URL pattern to one or more routes.
398
435
  #
399
- # You should not use the +match+ method in your router
400
- # without specifying an HTTP method.
436
+ # You should not use the `match` method in your router without specifying an
437
+ # HTTP method.
401
438
  #
402
439
  # If you want to expose your action to both GET and POST, use:
403
440
  #
404
- # # sets :controller, :action, and :id in params
405
- # match ':controller/:action/:id', via: [:get, :post]
441
+ # # sets :controller, :action, and :id in params
442
+ # match ':controller/:action/:id', via: [:get, :post]
406
443
  #
407
- # Note that +:controller+, +:action+, and +:id+ are interpreted as URL
408
- # query parameters and thus available through +params+ in an action.
444
+ # Note that `:controller`, `:action`, and `:id` are interpreted as URL query
445
+ # parameters and thus available through `params` in an action.
409
446
  #
410
- # If you want to expose your action to GET, use +get+ in the router:
447
+ # If you want to expose your action to GET, use `get` in the router:
411
448
  #
412
449
  # Instead of:
413
450
  #
414
- # match ":controller/:action/:id"
451
+ # match ":controller/:action/:id"
415
452
  #
416
453
  # Do:
417
454
  #
418
- # get ":controller/:action/:id"
455
+ # get ":controller/:action/:id"
419
456
  #
420
- # Two of these symbols are special, +:controller+ maps to the controller
421
- # and +:action+ to the controller's action. A pattern can also map
422
- # wildcard segments (globs) to params:
457
+ # Two of these symbols are special, `:controller` maps to the controller and
458
+ # `:action` to the controller's action. A pattern can also map wildcard segments
459
+ # (globs) to params:
423
460
  #
424
- # get 'songs/*category/:title', to: 'songs#show'
461
+ # get 'songs/*category/:title', to: 'songs#show'
425
462
  #
426
- # # 'songs/rock/classic/stairway-to-heaven' sets
427
- # # params[:category] = 'rock/classic'
428
- # # params[:title] = 'stairway-to-heaven'
463
+ # # 'songs/rock/classic/stairway-to-heaven' sets
464
+ # # params[:category] = 'rock/classic'
465
+ # # params[:title] = 'stairway-to-heaven'
429
466
  #
430
- # To match a wildcard parameter, it must have a name assigned to it.
431
- # Without a variable name to attach the glob parameter to, the route
432
- # can't be parsed.
467
+ # To match a wildcard parameter, it must have a name assigned to it. Without a
468
+ # variable name to attach the glob parameter to, the route can't be parsed.
433
469
  #
434
- # When a pattern points to an internal route, the route's +:action+ and
435
- # +:controller+ should be set in options or hash shorthand. Examples:
470
+ # When a pattern points to an internal route, the route's `:action` and
471
+ # `:controller` should be set in options or hash shorthand. Examples:
436
472
  #
437
- # match 'photos/:id' => 'photos#show', via: :get
438
- # match 'photos/:id', to: 'photos#show', via: :get
439
- # match 'photos/:id', controller: 'photos', action: 'show', via: :get
473
+ # match 'photos/:id' => 'photos#show', via: :get
474
+ # match 'photos/:id', to: 'photos#show', via: :get
475
+ # match 'photos/:id', controller: 'photos', action: 'show', via: :get
440
476
  #
441
- # A pattern can also point to a +Rack+ endpoint i.e. anything that
442
- # responds to +call+:
477
+ # A pattern can also point to a `Rack` endpoint i.e. anything that responds to
478
+ # `call`:
443
479
  #
444
- # match 'photos/:id', to: -> (hash) { [200, {}, ["Coming soon"]] }, via: :get
445
- # match 'photos/:id', to: PhotoRackApp, via: :get
446
- # # Yes, controller actions are just rack endpoints
447
- # match 'photos/:id', to: PhotosController.action(:show), via: :get
480
+ # match 'photos/:id', to: -> (hash) { [200, {}, ["Coming soon"]] }, via: :get
481
+ # match 'photos/:id', to: PhotoRackApp, via: :get
482
+ # # Yes, controller actions are just rack endpoints
483
+ # match 'photos/:id', to: PhotosController.action(:show), via: :get
448
484
  #
449
485
  # Because requesting various HTTP verbs with a single action has security
450
- # implications, you must either specify the actions in
451
- # the via options or use one of the HttpHelpers[rdoc-ref:HttpHelpers]
452
- # instead +match+
486
+ # implications, you must either specify the actions in the via options or use
487
+ # one of the [HttpHelpers](rdoc-ref:HttpHelpers) instead `match`
453
488
  #
454
- # === Options
489
+ # ### Options
455
490
  #
456
491
  # Any options not seen here are passed on as params with the URL.
457
492
  #
458
- # [:controller]
459
- # The route's controller.
493
+ # :controller
494
+ # : The route's controller.
460
495
  #
461
- # [:action]
462
- # The route's action.
496
+ # :action
497
+ # : The route's action.
463
498
  #
464
- # [:param]
465
- # Overrides the default resource identifier +:id+ (name of the
466
- # dynamic segment used to generate the routes).
467
- # You can access that segment from your controller using
468
- # <tt>params[<:param>]</tt>.
469
- # In your router:
499
+ # :param
500
+ # : Overrides the default resource identifier `:id` (name of the dynamic
501
+ # segment used to generate the routes). You can access that segment from
502
+ # your controller using `params[<:param>]`. In your router:
470
503
  #
471
- # resources :users, param: :name
504
+ # resources :users, param: :name
472
505
  #
473
- # The +users+ resource here will have the following routes generated for it:
506
+ # The `users` resource here will have the following routes generated for it:
474
507
  #
475
- # GET /users(.:format)
476
- # POST /users(.:format)
477
- # GET /users/new(.:format)
478
- # GET /users/:name/edit(.:format)
479
- # GET /users/:name(.:format)
480
- # PATCH/PUT /users/:name(.:format)
481
- # DELETE /users/:name(.:format)
508
+ # GET /users(.:format)
509
+ # POST /users(.:format)
510
+ # GET /users/new(.:format)
511
+ # GET /users/:name/edit(.:format)
512
+ # GET /users/:name(.:format)
513
+ # PATCH/PUT /users/:name(.:format)
514
+ # DELETE /users/:name(.:format)
482
515
  #
483
- # You can override <tt>ActiveRecord::Base#to_param</tt> of a related
484
- # model to construct a URL:
516
+ # You can override `ActiveRecord::Base#to_param` of a related model to
517
+ # construct a URL:
485
518
  #
486
- # class User < ActiveRecord::Base
487
- # def to_param
488
- # name
489
- # end
490
- # end
519
+ # class User < ActiveRecord::Base
520
+ # def to_param
521
+ # name
522
+ # end
523
+ # end
491
524
  #
492
- # user = User.find_by(name: 'Phusion')
493
- # user_path(user) # => "/users/Phusion"
525
+ # user = User.find_by(name: 'Phusion')
526
+ # user_path(user) # => "/users/Phusion"
494
527
  #
495
- # [:path]
496
- # The path prefix for the routes.
528
+ # :path
529
+ # : The path prefix for the routes.
497
530
  #
498
- # [:module]
499
- # The namespace for :controller.
531
+ # :module
532
+ # : The namespace for :controller.
500
533
  #
501
- # match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: :get
502
- # # => Sekret::PostsController
534
+ # match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: :get
535
+ # # => Sekret::PostsController
503
536
  #
504
- # See <tt>Scoping#namespace</tt> for its scope equivalent.
537
+ # See `Scoping#namespace` for its scope equivalent.
505
538
  #
506
- # [:as]
507
- # The name used to generate routing helpers.
539
+ # :as
540
+ # : The name used to generate routing helpers.
508
541
  #
509
- # [:via]
510
- # Allowed HTTP verb(s) for route.
542
+ # :via
543
+ # : Allowed HTTP verb(s) for route.
511
544
  #
512
- # match 'path', to: 'c#a', via: :get
513
- # match 'path', to: 'c#a', via: [:get, :post]
514
- # match 'path', to: 'c#a', via: :all
545
+ # match 'path', to: 'c#a', via: :get
546
+ # match 'path', to: 'c#a', via: [:get, :post]
547
+ # match 'path', to: 'c#a', via: :all
515
548
  #
516
- # [:to]
517
- # Points to a +Rack+ endpoint. Can be an object that responds to
518
- # +call+ or a string representing a controller's action.
549
+ # :to
550
+ # : Points to a `Rack` endpoint. Can be an object that responds to `call` or a
551
+ # string representing a controller's action.
519
552
  #
520
- # match 'path', to: 'controller#action', via: :get
521
- # match 'path', to: -> (env) { [200, {}, ["Success!"]] }, via: :get
522
- # match 'path', to: RackApp, via: :get
553
+ # match 'path', to: 'controller#action', via: :get
554
+ # match 'path', to: -> (env) { [200, {}, ["Success!"]] }, via: :get
555
+ # match 'path', to: RackApp, via: :get
523
556
  #
524
- # [:on]
525
- # Shorthand for wrapping routes in a specific RESTful context. Valid
526
- # values are +:member+, +:collection+, and +:new+. Only use within
527
- # <tt>resource(s)</tt> block. For example:
557
+ # :on
558
+ # : Shorthand for wrapping routes in a specific RESTful context. Valid values
559
+ # are `:member`, `:collection`, and `:new`. Only use within `resource(s)`
560
+ # block. For example:
528
561
  #
529
- # resource :bar do
530
- # match 'foo', to: 'c#a', on: :member, via: [:get, :post]
531
- # end
562
+ # resource :bar do
563
+ # match 'foo', to: 'c#a', on: :member, via: [:get, :post]
564
+ # end
532
565
  #
533
- # Is equivalent to:
566
+ # Is equivalent to:
534
567
  #
535
- # resource :bar do
536
- # member do
537
- # match 'foo', to: 'c#a', via: [:get, :post]
538
- # end
539
- # end
568
+ # resource :bar do
569
+ # member do
570
+ # match 'foo', to: 'c#a', via: [:get, :post]
571
+ # end
572
+ # end
540
573
  #
541
- # [:constraints]
542
- # Constrains parameters with a hash of regular expressions
543
- # or an object that responds to <tt>matches?</tt>. In addition, constraints
544
- # other than path can also be specified with any object
545
- # that responds to <tt>===</tt> (e.g. String, Array, Range, etc.).
574
+ # :constraints
575
+ # : Constrains parameters with a hash of regular expressions or an object that
576
+ # responds to `matches?`. In addition, constraints other than path can also
577
+ # be specified with any object that responds to `===` (e.g. String, Array,
578
+ # Range, etc.).
546
579
  #
547
- # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :get
580
+ # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :get
548
581
  #
549
- # match 'json_only', constraints: { format: 'json' }, via: :get
582
+ # match 'json_only', constraints: { format: 'json' }, via: :get
550
583
  #
551
- # class PermitList
552
- # def matches?(request) request.remote_ip == '1.2.3.4' end
553
- # end
554
- # match 'path', to: 'c#a', constraints: PermitList.new, via: :get
584
+ # class PermitList
585
+ # def matches?(request) request.remote_ip == '1.2.3.4' end
586
+ # end
587
+ # match 'path', to: 'c#a', constraints: PermitList.new, via: :get
555
588
  #
556
- # See <tt>Scoping#constraints</tt> for more examples with its scope
557
- # equivalent.
589
+ # See `Scoping#constraints` for more examples with its scope equivalent.
558
590
  #
559
- # [:defaults]
560
- # Sets defaults for parameters
591
+ # :defaults
592
+ # : Sets defaults for parameters
561
593
  #
562
- # # Sets params[:format] to 'jpg' by default
563
- # match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: :get
594
+ # # Sets params[:format] to 'jpg' by default
595
+ # match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: :get
564
596
  #
565
- # See <tt>Scoping#defaults</tt> for its scope equivalent.
597
+ # See `Scoping#defaults` for its scope equivalent.
566
598
  #
567
- # [:anchor]
568
- # Boolean to anchor a <tt>match</tt> pattern. Default is true. When set to
569
- # false, the pattern matches any request prefixed with the given path.
599
+ # :anchor
600
+ # : Boolean to anchor a `match` pattern. Default is true. When set to false,
601
+ # the pattern matches any request prefixed with the given path.
570
602
  #
571
- # # Matches any request starting with 'path'
572
- # match 'path', to: 'c#a', anchor: false, via: :get
603
+ # # Matches any request starting with 'path'
604
+ # match 'path', to: 'c#a', anchor: false, via: :get
605
+ #
606
+ # :format
607
+ # : Allows you to specify the default value for optional `format` segment or
608
+ # disable it by supplying `false`.
573
609
  #
574
- # [:format]
575
- # Allows you to specify the default value for optional +format+
576
- # segment or disable it by supplying +false+.
577
610
  def match(path, options = nil)
578
611
  end
579
612
 
580
613
  # Mount a Rack-based application to be used within the application.
581
614
  #
582
- # mount SomeRackApp, at: "some_route"
615
+ # mount SomeRackApp, at: "some_route"
583
616
  #
584
617
  # Alternatively:
585
618
  #
586
- # mount(SomeRackApp => "some_route")
619
+ # mount(SomeRackApp => "some_route")
587
620
  #
588
- # For options, see +match+, as +mount+ uses it internally.
621
+ # For options, see `match`, as `mount` uses it internally.
589
622
  #
590
- # All mounted applications come with routing helpers to access them.
591
- # These are named after the class specified, so for the above example
592
- # the helper is either +some_rack_app_path+ or +some_rack_app_url+.
593
- # To customize this helper's name, use the +:as+ option:
623
+ # All mounted applications come with routing helpers to access them. These are
624
+ # named after the class specified, so for the above example the helper is either
625
+ # `some_rack_app_path` or `some_rack_app_url`. To customize this helper's name,
626
+ # use the `:as` option:
594
627
  #
595
- # mount(SomeRackApp => "some_route", as: "exciting")
628
+ # mount(SomeRackApp => "some_route", as: "exciting")
596
629
  #
597
- # This will generate the +exciting_path+ and +exciting_url+ helpers
598
- # which can be used to navigate to this mounted app.
630
+ # This will generate the `exciting_path` and `exciting_url` helpers which can be
631
+ # used to navigate to this mounted app.
599
632
  def mount(app, options = nil)
600
633
  if options
601
634
  path = options.delete(:at)
@@ -669,7 +702,8 @@ module ActionDispatch
669
702
  prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys))
670
703
  end
671
704
 
672
- # We must actually delete prefix segment keys to avoid passing them to next url_for.
705
+ # We must actually delete prefix segment keys to avoid passing them to next
706
+ # url_for.
673
707
  _route.segment_keys.each { |k| options.delete(k) }
674
708
  _url_helpers.public_send("#{name}_path", prefix_options)
675
709
  end
@@ -691,50 +725,50 @@ module ActionDispatch
691
725
  end
692
726
 
693
727
  module HttpHelpers
694
- # Define a route that only recognizes HTTP GET.
695
- # For supported arguments, see match[rdoc-ref:Base#match]
728
+ # Define a route that only recognizes HTTP GET. For supported arguments, see
729
+ # [match](rdoc-ref:Base#match)
696
730
  #
697
- # get 'bacon', to: 'food#bacon'
731
+ # get 'bacon', to: 'food#bacon'
698
732
  def get(*args, &block)
699
733
  map_method(:get, args, &block)
700
734
  end
701
735
 
702
- # Define a route that only recognizes HTTP POST.
703
- # For supported arguments, see match[rdoc-ref:Base#match]
736
+ # Define a route that only recognizes HTTP POST. For supported arguments, see
737
+ # [match](rdoc-ref:Base#match)
704
738
  #
705
- # post 'bacon', to: 'food#bacon'
739
+ # post 'bacon', to: 'food#bacon'
706
740
  def post(*args, &block)
707
741
  map_method(:post, args, &block)
708
742
  end
709
743
 
710
- # Define a route that only recognizes HTTP PATCH.
711
- # For supported arguments, see match[rdoc-ref:Base#match]
744
+ # Define a route that only recognizes HTTP PATCH. For supported arguments, see
745
+ # [match](rdoc-ref:Base#match)
712
746
  #
713
- # patch 'bacon', to: 'food#bacon'
747
+ # patch 'bacon', to: 'food#bacon'
714
748
  def patch(*args, &block)
715
749
  map_method(:patch, args, &block)
716
750
  end
717
751
 
718
- # Define a route that only recognizes HTTP PUT.
719
- # For supported arguments, see match[rdoc-ref:Base#match]
752
+ # Define a route that only recognizes HTTP PUT. For supported arguments, see
753
+ # [match](rdoc-ref:Base#match)
720
754
  #
721
- # put 'bacon', to: 'food#bacon'
755
+ # put 'bacon', to: 'food#bacon'
722
756
  def put(*args, &block)
723
757
  map_method(:put, args, &block)
724
758
  end
725
759
 
726
- # Define a route that only recognizes HTTP DELETE.
727
- # For supported arguments, see match[rdoc-ref:Base#match]
760
+ # Define a route that only recognizes HTTP DELETE. For supported arguments, see
761
+ # [match](rdoc-ref:Base#match)
728
762
  #
729
- # delete 'broccoli', to: 'food#broccoli'
763
+ # delete 'broccoli', to: 'food#broccoli'
730
764
  def delete(*args, &block)
731
765
  map_method(:delete, args, &block)
732
766
  end
733
767
 
734
- # Define a route that only recognizes HTTP OPTIONS.
735
- # For supported arguments, see match[rdoc-ref:Base#match]
768
+ # Define a route that only recognizes HTTP OPTIONS. For supported arguments, see
769
+ # [match](rdoc-ref:Base#match)
736
770
  #
737
- # options 'carrots', to: 'food#carrots'
771
+ # options 'carrots', to: 'food#carrots'
738
772
  def options(*args, &block)
739
773
  map_method(:options, args, &block)
740
774
  end
@@ -748,91 +782,90 @@ module ActionDispatch
748
782
  end
749
783
  end
750
784
 
751
- # You may wish to organize groups of controllers under a namespace.
752
- # Most commonly, you might group a number of administrative controllers
753
- # under an +admin+ namespace. You would place these controllers under
754
- # the <tt>app/controllers/admin</tt> directory, and you can group them
755
- # together in your router:
785
+ # You may wish to organize groups of controllers under a namespace. Most
786
+ # commonly, you might group a number of administrative controllers under an
787
+ # `admin` namespace. You would place these controllers under the
788
+ # `app/controllers/admin` directory, and you can group them together in your
789
+ # router:
756
790
  #
757
- # namespace "admin" do
758
- # resources :posts, :comments
759
- # end
791
+ # namespace "admin" do
792
+ # resources :posts, :comments
793
+ # end
760
794
  #
761
795
  # This will create a number of routes for each of the posts and comments
762
- # controller. For +Admin::PostsController+, \Rails will create:
796
+ # controller. For `Admin::PostsController`, Rails will create:
763
797
  #
764
- # GET /admin/posts
765
- # GET /admin/posts/new
766
- # POST /admin/posts
767
- # GET /admin/posts/1
768
- # GET /admin/posts/1/edit
769
- # PATCH/PUT /admin/posts/1
770
- # DELETE /admin/posts/1
798
+ # GET /admin/posts
799
+ # GET /admin/posts/new
800
+ # POST /admin/posts
801
+ # GET /admin/posts/1
802
+ # GET /admin/posts/1/edit
803
+ # PATCH/PUT /admin/posts/1
804
+ # DELETE /admin/posts/1
771
805
  #
772
806
  # If you want to route /posts (without the prefix /admin) to
773
- # +Admin::PostsController+, you could use
807
+ # `Admin::PostsController`, you could use
774
808
  #
775
- # scope module: "admin" do
776
- # resources :posts
777
- # end
809
+ # scope module: "admin" do
810
+ # resources :posts
811
+ # end
778
812
  #
779
813
  # or, for a single case
780
814
  #
781
- # resources :posts, module: "admin"
815
+ # resources :posts, module: "admin"
782
816
  #
783
- # If you want to route /admin/posts to +PostsController+
784
- # (without the <tt>Admin::</tt> module prefix), you could use
817
+ # If you want to route /admin/posts to `PostsController` (without the `Admin::`
818
+ # module prefix), you could use
785
819
  #
786
- # scope "/admin" do
787
- # resources :posts
788
- # end
820
+ # scope "/admin" do
821
+ # resources :posts
822
+ # end
789
823
  #
790
824
  # or, for a single case
791
825
  #
792
- # resources :posts, path: "/admin/posts"
826
+ # resources :posts, path: "/admin/posts"
793
827
  #
794
- # In each of these cases, the named routes remain the same as if you did
795
- # not use scope. In the last case, the following paths map to
796
- # +PostsController+:
828
+ # In each of these cases, the named routes remain the same as if you did not use
829
+ # scope. In the last case, the following paths map to `PostsController`:
797
830
  #
798
- # GET /admin/posts
799
- # GET /admin/posts/new
800
- # POST /admin/posts
801
- # GET /admin/posts/1
802
- # GET /admin/posts/1/edit
803
- # PATCH/PUT /admin/posts/1
804
- # DELETE /admin/posts/1
831
+ # GET /admin/posts
832
+ # GET /admin/posts/new
833
+ # POST /admin/posts
834
+ # GET /admin/posts/1
835
+ # GET /admin/posts/1/edit
836
+ # PATCH/PUT /admin/posts/1
837
+ # DELETE /admin/posts/1
805
838
  module Scoping
806
839
  # Scopes a set of routes to the given default options.
807
840
  #
808
841
  # Take the following route definition as an example:
809
842
  #
810
- # scope path: ":account_id", as: "account" do
811
- # resources :projects
812
- # end
843
+ # scope path: ":account_id", as: "account" do
844
+ # resources :projects
845
+ # end
813
846
  #
814
- # This generates helpers such as +account_projects_path+, just like +resources+ does.
815
- # The difference here being that the routes generated are like /:account_id/projects,
816
- # rather than /accounts/:account_id/projects.
847
+ # This generates helpers such as `account_projects_path`, just like `resources`
848
+ # does. The difference here being that the routes generated are like
849
+ # /:account_id/projects, rather than /accounts/:account_id/projects.
817
850
  #
818
- # === Options
851
+ # ### Options
819
852
  #
820
- # Takes same options as <tt>Base#match</tt> and <tt>Resources#resources</tt>.
853
+ # Takes same options as `Base#match` and `Resources#resources`.
821
854
  #
822
- # # route /posts (without the prefix /admin) to +Admin::PostsController+
823
- # scope module: "admin" do
824
- # resources :posts
825
- # end
855
+ # # route /posts (without the prefix /admin) to +Admin::PostsController+
856
+ # scope module: "admin" do
857
+ # resources :posts
858
+ # end
826
859
  #
827
- # # prefix the posts resource's requests with '/admin'
828
- # scope path: "/admin" do
829
- # resources :posts
830
- # end
860
+ # # prefix the posts resource's requests with '/admin'
861
+ # scope path: "/admin" do
862
+ # resources :posts
863
+ # end
831
864
  #
832
- # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
833
- # scope as: "sekret" do
834
- # resources :posts
835
- # end
865
+ # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
866
+ # scope as: "sekret" do
867
+ # resources :posts
868
+ # end
836
869
  def scope(*args)
837
870
  options = args.extract_options!.dup
838
871
  scope = {}
@@ -889,9 +922,9 @@ module ActionDispatch
889
922
 
890
923
  # Scopes routes to a specific controller
891
924
  #
892
- # controller "food" do
893
- # match "bacon", action: :bacon, via: :get
894
- # end
925
+ # controller "food" do
926
+ # match "bacon", action: :bacon, via: :get
927
+ # end
895
928
  def controller(controller)
896
929
  @scope = @scope.new(controller: controller)
897
930
  yield
@@ -901,42 +934,42 @@ module ActionDispatch
901
934
 
902
935
  # Scopes routes to a specific namespace. For example:
903
936
  #
904
- # namespace :admin do
905
- # resources :posts
906
- # end
937
+ # namespace :admin do
938
+ # resources :posts
939
+ # end
907
940
  #
908
941
  # This generates the following routes:
909
942
  #
910
- # admin_posts GET /admin/posts(.:format) admin/posts#index
911
- # admin_posts POST /admin/posts(.:format) admin/posts#create
912
- # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
913
- # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
914
- # admin_post GET /admin/posts/:id(.:format) admin/posts#show
915
- # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
916
- # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
943
+ # admin_posts GET /admin/posts(.:format) admin/posts#index
944
+ # admin_posts POST /admin/posts(.:format) admin/posts#create
945
+ # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
946
+ # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
947
+ # admin_post GET /admin/posts/:id(.:format) admin/posts#show
948
+ # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
949
+ # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
917
950
  #
918
- # === Options
951
+ # ### Options
919
952
  #
920
- # The +:path+, +:as+, +:module+, +:shallow_path+, and +:shallow_prefix+
921
- # options all default to the name of the namespace.
953
+ # The `:path`, `:as`, `:module`, `:shallow_path`, and `:shallow_prefix` options
954
+ # all default to the name of the namespace.
922
955
  #
923
- # For options, see <tt>Base#match</tt>. For +:shallow_path+ option, see
924
- # <tt>Resources#resources</tt>.
956
+ # For options, see `Base#match`. For `:shallow_path` option, see
957
+ # `Resources#resources`.
925
958
  #
926
- # # accessible through /sekret/posts rather than /admin/posts
927
- # namespace :admin, path: "sekret" do
928
- # resources :posts
929
- # end
959
+ # # accessible through /sekret/posts rather than /admin/posts
960
+ # namespace :admin, path: "sekret" do
961
+ # resources :posts
962
+ # end
930
963
  #
931
- # # maps to +Sekret::PostsController+ rather than +Admin::PostsController+
932
- # namespace :admin, module: "sekret" do
933
- # resources :posts
934
- # end
964
+ # # maps to +Sekret::PostsController+ rather than +Admin::PostsController+
965
+ # namespace :admin, module: "sekret" do
966
+ # resources :posts
967
+ # end
935
968
  #
936
- # # generates +sekret_posts_path+ rather than +admin_posts_path+
937
- # namespace :admin, as: "sekret" do
938
- # resources :posts
939
- # end
969
+ # # generates +sekret_posts_path+ rather than +admin_posts_path+
970
+ # namespace :admin, as: "sekret" do
971
+ # resources :posts
972
+ # end
940
973
  def namespace(path, options = {}, &block)
941
974
  path = path.to_s
942
975
 
@@ -952,70 +985,74 @@ module ActionDispatch
952
985
  end
953
986
  end
954
987
 
955
- # === Parameter Restriction
956
- # Allows you to constrain the nested routes based on a set of rules.
957
- # For instance, in order to change the routes to allow for a dot character in the +id+ parameter:
988
+ # ### Parameter Restriction
989
+ # Allows you to constrain the nested routes based on a set of rules. For
990
+ # instance, in order to change the routes to allow for a dot character in the
991
+ # `id` parameter:
958
992
  #
959
- # constraints(id: /\d+\.\d+/) do
960
- # resources :posts
961
- # end
993
+ # constraints(id: /\d+\.\d+/) do
994
+ # resources :posts
995
+ # end
962
996
  #
963
- # Now routes such as +/posts/1+ will no longer be valid, but +/posts/1.1+ will be.
964
- # The +id+ parameter must match the constraint passed in for this example.
997
+ # Now routes such as `/posts/1` will no longer be valid, but `/posts/1.1` will
998
+ # be. The `id` parameter must match the constraint passed in for this example.
965
999
  #
966
1000
  # You may use this to also restrict other parameters:
967
1001
  #
968
- # resources :posts do
969
- # constraints(post_id: /\d+\.\d+/) do
970
- # resources :comments
1002
+ # resources :posts do
1003
+ # constraints(post_id: /\d+\.\d+/) do
1004
+ # resources :comments
1005
+ # end
971
1006
  # end
972
- # end
973
1007
  #
974
- # === Restricting based on IP
1008
+ # ### Restricting based on IP
975
1009
  #
976
1010
  # Routes can also be constrained to an IP or a certain range of IP addresses:
977
1011
  #
978
- # constraints(ip: /192\.168\.\d+\.\d+/) do
979
- # resources :posts
980
- # end
1012
+ # constraints(ip: /192\.168\.\d+\.\d+/) do
1013
+ # resources :posts
1014
+ # end
981
1015
  #
982
- # Any user connecting from the 192.168.* range will be able to see this resource,
983
- # where as any user connecting outside of this range will be told there is no such route.
1016
+ # Any user connecting from the 192.168.* range will be able to see this
1017
+ # resource, where as any user connecting outside of this range will be told
1018
+ # there is no such route.
984
1019
  #
985
- # === Dynamic request matching
1020
+ # ### Dynamic request matching
986
1021
  #
987
1022
  # Requests to routes can be constrained based on specific criteria:
988
1023
  #
989
- # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
990
- # resources :iphones
991
- # end
1024
+ # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
1025
+ # resources :iphones
1026
+ # end
992
1027
  #
993
- # You are able to move this logic out into a class if it is too complex for routes.
994
- # This class must have a +matches?+ method defined on it which either returns +true+
995
- # if the user should be given access to that route, or +false+ if the user should not.
1028
+ # You are able to move this logic out into a class if it is too complex for
1029
+ # routes. This class must have a `matches?` method defined on it which either
1030
+ # returns `true` if the user should be given access to that route, or `false` if
1031
+ # the user should not.
996
1032
  #
997
- # class Iphone
998
- # def self.matches?(request)
999
- # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
1000
- # end
1001
- # end
1033
+ # class Iphone
1034
+ # def self.matches?(request)
1035
+ # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
1036
+ # end
1037
+ # end
1002
1038
  #
1003
- # An expected place for this code would be +lib/constraints+.
1039
+ # An expected place for this code would be `lib/constraints`.
1004
1040
  #
1005
1041
  # This class is then used like this:
1006
1042
  #
1007
- # constraints(Iphone) do
1008
- # resources :iphones
1009
- # end
1043
+ # constraints(Iphone) do
1044
+ # resources :iphones
1045
+ # end
1010
1046
  def constraints(constraints = {}, &block)
1011
1047
  scope(constraints: constraints, &block)
1012
1048
  end
1013
1049
 
1014
1050
  # Allows you to set default parameters for a route, such as this:
1015
- # defaults id: 'home' do
1016
- # match 'scoped_pages/(:id)', to: 'pages#show'
1017
- # end
1018
- # Using this, the +:id+ parameter here will default to 'home'.
1051
+ # defaults id: 'home' do
1052
+ # match 'scoped_pages/(:id)', to: 'pages#show'
1053
+ # end
1054
+ #
1055
+ # Using this, the `:id` parameter here will default to 'home'.
1019
1056
  def defaults(defaults = {})
1020
1057
  @scope = @scope.new(defaults: merge_defaults_scope(@scope[:defaults], defaults))
1021
1058
  yield
@@ -1091,48 +1128,46 @@ module ActionDispatch
1091
1128
  end
1092
1129
  end
1093
1130
 
1094
- # Resource routing allows you to quickly declare all of the common routes
1095
- # for a given resourceful controller. Instead of declaring separate routes
1096
- # for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
1097
- # actions, a resourceful route declares them in a single line of code:
1131
+ # Resource routing allows you to quickly declare all of the common routes for a
1132
+ # given resourceful controller. Instead of declaring separate routes for your
1133
+ # `index`, `show`, `new`, `edit`, `create`, `update`, and `destroy` actions, a
1134
+ # resourceful route declares them in a single line of code:
1098
1135
  #
1099
- # resources :photos
1136
+ # resources :photos
1100
1137
  #
1101
- # Sometimes, you have a resource that clients always look up without
1102
- # referencing an ID. A common example, /profile always shows the profile of
1103
- # the currently logged in user. In this case, you can use a singular resource
1104
- # to map /profile (rather than /profile/:id) to the show action.
1138
+ # Sometimes, you have a resource that clients always look up without referencing
1139
+ # an ID. A common example, /profile always shows the profile of the currently
1140
+ # logged in user. In this case, you can use a singular resource to map /profile
1141
+ # (rather than /profile/:id) to the show action.
1105
1142
  #
1106
- # resource :profile
1143
+ # resource :profile
1107
1144
  #
1108
- # It's common to have resources that are logically children of other
1109
- # resources:
1145
+ # It's common to have resources that are logically children of other resources:
1110
1146
  #
1111
- # resources :magazines do
1112
- # resources :ads
1113
- # end
1147
+ # resources :magazines do
1148
+ # resources :ads
1149
+ # end
1114
1150
  #
1115
1151
  # You may wish to organize groups of controllers under a namespace. Most
1116
- # commonly, you might group a number of administrative controllers under
1117
- # an +admin+ namespace. You would place these controllers under the
1118
- # <tt>app/controllers/admin</tt> directory, and you can group them together
1119
- # in your router:
1120
- #
1121
- # namespace "admin" do
1122
- # resources :posts, :comments
1123
- # end
1152
+ # commonly, you might group a number of administrative controllers under an
1153
+ # `admin` namespace. You would place these controllers under the
1154
+ # `app/controllers/admin` directory, and you can group them together in your
1155
+ # router:
1124
1156
  #
1125
- # By default the +:id+ parameter doesn't accept dots. If you need to
1126
- # use dots as part of the +:id+ parameter add a constraint which
1127
- # overrides this restriction, e.g:
1157
+ # namespace "admin" do
1158
+ # resources :posts, :comments
1159
+ # end
1128
1160
  #
1129
- # resources :articles, id: /[^\/]+/
1161
+ # By default the `:id` parameter doesn't accept dots. If you need to use dots as
1162
+ # part of the `:id` parameter add a constraint which overrides this restriction,
1163
+ # e.g:
1130
1164
  #
1131
- # This allows any character other than a slash as part of your +:id+.
1165
+ # resources :articles, id: /[^\/]+/
1132
1166
  #
1167
+ # This allows any character other than a slash as part of your `:id`.
1133
1168
  module Resources
1134
- # CANONICAL_ACTIONS holds all actions that does not need a prefix or
1135
- # a path appended since they fit properly in their scope level.
1169
+ # CANONICAL_ACTIONS holds all actions that does not need a prefix or a path
1170
+ # appended since they fit properly in their scope level.
1136
1171
  VALID_ON_OPTIONS = [:new, :collection, :member]
1137
1172
  RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except, :param, :concerns]
1138
1173
  CANONICAL_ACTIONS = %w(index create new show update destroy)
@@ -1195,8 +1230,8 @@ module ActionDispatch
1195
1230
 
1196
1231
  alias :member_name :singular
1197
1232
 
1198
- # Checks for uncountable plurals, and appends "_index" if the plural
1199
- # and singular form are the same.
1233
+ # Checks for uncountable plurals, and appends "_index" if the plural and
1234
+ # singular form are the same.
1200
1235
  def collection_name
1201
1236
  singular == plural ? "#{plural}_index" : plural
1202
1237
  end
@@ -1269,37 +1304,35 @@ module ActionDispatch
1269
1304
  @scope[:path_names].merge!(options)
1270
1305
  end
1271
1306
 
1272
- # Sometimes, you have a resource that clients always look up without
1273
- # referencing an ID. A common example, /profile always shows the
1274
- # profile of the currently logged in user. In this case, you can use
1275
- # a singular resource to map /profile (rather than /profile/:id) to
1276
- # the show action:
1307
+ # Sometimes, you have a resource that clients always look up without referencing
1308
+ # an ID. A common example, /profile always shows the profile of the currently
1309
+ # logged in user. In this case, you can use a singular resource to map /profile
1310
+ # (rather than /profile/:id) to the show action:
1277
1311
  #
1278
- # resource :profile
1312
+ # resource :profile
1279
1313
  #
1280
- # This creates six different routes in your application, all mapping to
1281
- # the +Profiles+ controller (note that the controller is named after
1282
- # the plural):
1314
+ # This creates six different routes in your application, all mapping to the
1315
+ # `Profiles` controller (note that the controller is named after the plural):
1283
1316
  #
1284
- # GET /profile/new
1285
- # GET /profile
1286
- # GET /profile/edit
1287
- # PATCH/PUT /profile
1288
- # DELETE /profile
1289
- # POST /profile
1317
+ # GET /profile/new
1318
+ # GET /profile
1319
+ # GET /profile/edit
1320
+ # PATCH/PUT /profile
1321
+ # DELETE /profile
1322
+ # POST /profile
1290
1323
  #
1291
- # If you want instances of a model to work with this resource via
1292
- # record identification (e.g. in +form_with+ or +redirect_to+), you
1293
- # will need to call resolve[rdoc-ref:CustomUrls#resolve]:
1324
+ # If you want instances of a model to work with this resource via record
1325
+ # identification (e.g. in `form_with` or `redirect_to`), you will need to call
1326
+ # [resolve](rdoc-ref:CustomUrls#resolve):
1294
1327
  #
1295
- # resource :profile
1296
- # resolve('Profile') { [:profile] }
1328
+ # resource :profile
1329
+ # resolve('Profile') { [:profile] }
1297
1330
  #
1298
- # # Enables this to work with singular routes:
1299
- # form_with(model: @profile) {}
1331
+ # # Enables this to work with singular routes:
1332
+ # form_with(model: @profile) {}
1300
1333
  #
1301
- # === Options
1302
- # Takes same options as resources[rdoc-ref:#resources]
1334
+ # ### Options
1335
+ # Takes same options as [resources](rdoc-ref:#resources)
1303
1336
  def resource(*resources, &block)
1304
1337
  options = resources.extract_options!.dup
1305
1338
 
@@ -1329,143 +1362,147 @@ module ActionDispatch
1329
1362
  self
1330
1363
  end
1331
1364
 
1332
- # In \Rails, a resourceful route provides a mapping between HTTP verbs
1333
- # and URLs and controller actions. By convention, each action also maps
1334
- # to particular CRUD operations in a database. A single entry in the
1335
- # routing file, such as
1365
+ # In Rails, a resourceful route provides a mapping between HTTP verbs and URLs
1366
+ # and controller actions. By convention, each action also maps to particular
1367
+ # CRUD operations in a database. A single entry in the routing file, such as
1336
1368
  #
1337
- # resources :photos
1369
+ # resources :photos
1338
1370
  #
1339
- # creates seven different routes in your application, all mapping to
1340
- # the +Photos+ controller:
1371
+ # creates seven different routes in your application, all mapping to the
1372
+ # `Photos` controller:
1341
1373
  #
1342
- # GET /photos
1343
- # GET /photos/new
1344
- # POST /photos
1345
- # GET /photos/:id
1346
- # GET /photos/:id/edit
1347
- # PATCH/PUT /photos/:id
1348
- # DELETE /photos/:id
1374
+ # GET /photos
1375
+ # GET /photos/new
1376
+ # POST /photos
1377
+ # GET /photos/:id
1378
+ # GET /photos/:id/edit
1379
+ # PATCH/PUT /photos/:id
1380
+ # DELETE /photos/:id
1349
1381
  #
1350
1382
  # Resources can also be nested infinitely by using this block syntax:
1351
1383
  #
1352
- # resources :photos do
1353
- # resources :comments
1354
- # end
1384
+ # resources :photos do
1385
+ # resources :comments
1386
+ # end
1355
1387
  #
1356
1388
  # This generates the following comments routes:
1357
1389
  #
1358
- # GET /photos/:photo_id/comments
1359
- # GET /photos/:photo_id/comments/new
1360
- # POST /photos/:photo_id/comments
1361
- # GET /photos/:photo_id/comments/:id
1362
- # GET /photos/:photo_id/comments/:id/edit
1363
- # PATCH/PUT /photos/:photo_id/comments/:id
1364
- # DELETE /photos/:photo_id/comments/:id
1390
+ # GET /photos/:photo_id/comments
1391
+ # GET /photos/:photo_id/comments/new
1392
+ # POST /photos/:photo_id/comments
1393
+ # GET /photos/:photo_id/comments/:id
1394
+ # GET /photos/:photo_id/comments/:id/edit
1395
+ # PATCH/PUT /photos/:photo_id/comments/:id
1396
+ # DELETE /photos/:photo_id/comments/:id
1365
1397
  #
1366
- # === Options
1367
- # Takes same options as match[rdoc-ref:Base#match] as well as:
1398
+ # ### Options
1399
+ # Takes same options as [match](rdoc-ref:Base#match) as well as:
1368
1400
  #
1369
- # [:path_names]
1370
- # Allows you to change the segment component of the +edit+ and +new+ actions.
1371
- # Actions not specified are not changed.
1401
+ # :path_names
1402
+ # : Allows you to change the segment component of the `edit` and `new`
1403
+ # actions. Actions not specified are not changed.
1372
1404
  #
1373
- # resources :posts, path_names: { new: "brand_new" }
1405
+ # resources :posts, path_names: { new: "brand_new" }
1374
1406
  #
1375
- # The above example will now change /posts/new to /posts/brand_new.
1407
+ # The above example will now change /posts/new to /posts/brand_new.
1376
1408
  #
1377
- # [:path]
1378
- # Allows you to change the path prefix for the resource.
1409
+ # :path
1410
+ # : Allows you to change the path prefix for the resource.
1379
1411
  #
1380
- # resources :posts, path: 'postings'
1412
+ # resources :posts, path: 'postings'
1381
1413
  #
1382
- # The resource and all segments will now route to /postings instead of /posts.
1414
+ # The resource and all segments will now route to /postings instead of
1415
+ # /posts.
1383
1416
  #
1384
- # [:only]
1385
- # Only generate routes for the given actions.
1417
+ # :only
1418
+ # : Only generate routes for the given actions.
1386
1419
  #
1387
- # resources :cows, only: :show
1388
- # resources :cows, only: [:show, :index]
1420
+ # resources :cows, only: :show
1421
+ # resources :cows, only: [:show, :index]
1389
1422
  #
1390
- # [:except]
1391
- # Generate all routes except for the given actions.
1423
+ # :except
1424
+ # : Generate all routes except for the given actions.
1392
1425
  #
1393
- # resources :cows, except: :show
1394
- # resources :cows, except: [:show, :index]
1426
+ # resources :cows, except: :show
1427
+ # resources :cows, except: [:show, :index]
1395
1428
  #
1396
- # [:shallow]
1397
- # Generates shallow routes for nested resource(s). When placed on a parent resource,
1398
- # generates shallow routes for all nested resources.
1429
+ # :shallow
1430
+ # : Generates shallow routes for nested resource(s). When placed on a parent
1431
+ # resource, generates shallow routes for all nested resources.
1399
1432
  #
1400
- # resources :posts, shallow: true do
1401
- # resources :comments
1402
- # end
1433
+ # resources :posts, shallow: true do
1434
+ # resources :comments
1435
+ # end
1403
1436
  #
1404
- # Is the same as:
1437
+ # Is the same as:
1405
1438
  #
1406
- # resources :posts do
1407
- # resources :comments, except: [:show, :edit, :update, :destroy]
1408
- # end
1409
- # resources :comments, only: [:show, :edit, :update, :destroy]
1439
+ # resources :posts do
1440
+ # resources :comments, except: [:show, :edit, :update, :destroy]
1441
+ # end
1442
+ # resources :comments, only: [:show, :edit, :update, :destroy]
1410
1443
  #
1411
- # This allows URLs for resources that otherwise would be deeply nested such
1412
- # as a comment on a blog post like <tt>/posts/a-long-permalink/comments/1234</tt>
1413
- # to be shortened to just <tt>/comments/1234</tt>.
1444
+ # This allows URLs for resources that otherwise would be deeply nested such
1445
+ # as a comment on a blog post like `/posts/a-long-permalink/comments/1234`
1446
+ # to be shortened to just `/comments/1234`.
1414
1447
  #
1415
- # Set <tt>shallow: false</tt> on a child resource to ignore a parent's shallow parameter.
1448
+ # Set `shallow: false` on a child resource to ignore a parent's shallow
1449
+ # parameter.
1416
1450
  #
1417
- # [:shallow_path]
1418
- # Prefixes nested shallow routes with the specified path.
1451
+ # :shallow_path
1452
+ # : Prefixes nested shallow routes with the specified path.
1419
1453
  #
1420
- # scope shallow_path: "sekret" do
1421
- # resources :posts do
1422
- # resources :comments, shallow: true
1423
- # end
1424
- # end
1454
+ # scope shallow_path: "sekret" do
1455
+ # resources :posts do
1456
+ # resources :comments, shallow: true
1457
+ # end
1458
+ # end
1425
1459
  #
1426
- # The +comments+ resource here will have the following routes generated for it:
1460
+ # The `comments` resource here will have the following routes generated for
1461
+ # it:
1427
1462
  #
1428
- # post_comments GET /posts/:post_id/comments(.:format)
1429
- # post_comments POST /posts/:post_id/comments(.:format)
1430
- # new_post_comment GET /posts/:post_id/comments/new(.:format)
1431
- # edit_comment GET /sekret/comments/:id/edit(.:format)
1432
- # comment GET /sekret/comments/:id(.:format)
1433
- # comment PATCH/PUT /sekret/comments/:id(.:format)
1434
- # comment DELETE /sekret/comments/:id(.:format)
1463
+ # post_comments GET /posts/:post_id/comments(.:format)
1464
+ # post_comments POST /posts/:post_id/comments(.:format)
1465
+ # new_post_comment GET /posts/:post_id/comments/new(.:format)
1466
+ # edit_comment GET /sekret/comments/:id/edit(.:format)
1467
+ # comment GET /sekret/comments/:id(.:format)
1468
+ # comment PATCH/PUT /sekret/comments/:id(.:format)
1469
+ # comment DELETE /sekret/comments/:id(.:format)
1435
1470
  #
1436
- # [:shallow_prefix]
1437
- # Prefixes nested shallow route names with specified prefix.
1471
+ # :shallow_prefix
1472
+ # : Prefixes nested shallow route names with specified prefix.
1438
1473
  #
1439
- # scope shallow_prefix: "sekret" do
1440
- # resources :posts do
1441
- # resources :comments, shallow: true
1442
- # end
1443
- # end
1474
+ # scope shallow_prefix: "sekret" do
1475
+ # resources :posts do
1476
+ # resources :comments, shallow: true
1477
+ # end
1478
+ # end
1479
+ #
1480
+ # The `comments` resource here will have the following routes generated for
1481
+ # it:
1444
1482
  #
1445
- # The +comments+ resource here will have the following routes generated for it:
1483
+ # post_comments GET /posts/:post_id/comments(.:format)
1484
+ # post_comments POST /posts/:post_id/comments(.:format)
1485
+ # new_post_comment GET /posts/:post_id/comments/new(.:format)
1486
+ # edit_sekret_comment GET /comments/:id/edit(.:format)
1487
+ # sekret_comment GET /comments/:id(.:format)
1488
+ # sekret_comment PATCH/PUT /comments/:id(.:format)
1489
+ # sekret_comment DELETE /comments/:id(.:format)
1446
1490
  #
1447
- # post_comments GET /posts/:post_id/comments(.:format)
1448
- # post_comments POST /posts/:post_id/comments(.:format)
1449
- # new_post_comment GET /posts/:post_id/comments/new(.:format)
1450
- # edit_sekret_comment GET /comments/:id/edit(.:format)
1451
- # sekret_comment GET /comments/:id(.:format)
1452
- # sekret_comment PATCH/PUT /comments/:id(.:format)
1453
- # sekret_comment DELETE /comments/:id(.:format)
1491
+ # :format
1492
+ # : Allows you to specify the default value for optional `format` segment or
1493
+ # disable it by supplying `false`.
1454
1494
  #
1455
- # [:format]
1456
- # Allows you to specify the default value for optional +format+
1457
- # segment or disable it by supplying +false+.
1495
+ # :param
1496
+ # : Allows you to override the default param name of `:id` in the URL.
1458
1497
  #
1459
- # [:param]
1460
- # Allows you to override the default param name of +:id+ in the URL.
1461
1498
  #
1462
- # === Examples
1499
+ # ### Examples
1463
1500
  #
1464
- # # routes call +Admin::PostsController+
1465
- # resources :posts, module: "admin"
1501
+ # # routes call +Admin::PostsController+
1502
+ # resources :posts, module: "admin"
1466
1503
  #
1467
- # # resource actions are at /admin/posts.
1468
- # resources :posts, path: "admin/posts"
1504
+ # # resource actions are at /admin/posts.
1505
+ # resources :posts, path: "admin/posts"
1469
1506
  def resources(*resources, &block)
1470
1507
  options = resources.extract_options!.dup
1471
1508
 
@@ -1498,16 +1535,15 @@ module ActionDispatch
1498
1535
 
1499
1536
  # To add a route to the collection:
1500
1537
  #
1501
- # resources :photos do
1502
- # collection do
1503
- # get 'search'
1538
+ # resources :photos do
1539
+ # collection do
1540
+ # get 'search'
1541
+ # end
1504
1542
  # end
1505
- # end
1506
1543
  #
1507
- # This will enable \Rails to recognize paths such as <tt>/photos/search</tt>
1508
- # with GET, and route to the search action of +PhotosController+. It will also
1509
- # create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
1510
- # route helpers.
1544
+ # This will enable Rails to recognize paths such as `/photos/search` with GET,
1545
+ # and route to the search action of `PhotosController`. It will also create the
1546
+ # `search_photos_url` and `search_photos_path` route helpers.
1511
1547
  def collection(&block)
1512
1548
  unless resource_scope?
1513
1549
  raise ArgumentError, "can't use collection outside resource(s) scope"
@@ -1520,15 +1556,15 @@ module ActionDispatch
1520
1556
 
1521
1557
  # To add a member route, add a member block into the resource block:
1522
1558
  #
1523
- # resources :photos do
1524
- # member do
1525
- # get 'preview'
1559
+ # resources :photos do
1560
+ # member do
1561
+ # get 'preview'
1562
+ # end
1526
1563
  # end
1527
- # end
1528
1564
  #
1529
- # This will recognize <tt>/photos/1/preview</tt> with GET, and route to the
1530
- # preview action of +PhotosController+. It will also create the
1531
- # <tt>preview_photo_url</tt> and <tt>preview_photo_path</tt> helpers.
1565
+ # This will recognize `/photos/1/preview` with GET, and route to the preview
1566
+ # action of `PhotosController`. It will also create the `preview_photo_url` and
1567
+ # `preview_photo_path` helpers.
1532
1568
  def member(&block)
1533
1569
  unless resource_scope?
1534
1570
  raise ArgumentError, "can't use member outside resource(s) scope"
@@ -1595,29 +1631,28 @@ module ActionDispatch
1595
1631
  !parent_resource.singleton? && @scope[:shallow]
1596
1632
  end
1597
1633
 
1598
- # Loads another routes file with the given +name+ located inside the
1599
- # +config/routes+ directory. In that file, you can use the normal
1600
- # routing DSL, but <i>do not</i> surround it with a
1601
- # +Rails.application.routes.draw+ block.
1602
- #
1603
- # # config/routes.rb
1604
- # Rails.application.routes.draw do
1605
- # draw :admin # Loads `config/routes/admin.rb`
1606
- # draw "third_party/some_gem" # Loads `config/routes/third_party/some_gem.rb`
1607
- # end
1608
- #
1609
- # # config/routes/admin.rb
1610
- # namespace :admin do
1611
- # resources :accounts
1612
- # end
1613
- #
1614
- # # config/routes/third_party/some_gem.rb
1615
- # mount SomeGem::Engine, at: "/some_gem"
1616
- #
1617
- # <b>CAUTION:</b> Use this feature with care. Having multiple routes
1618
- # files can negatively impact discoverability and readability. For most
1619
- # applications — even those with a few hundred routes — it's easier for
1620
- # developers to have a single routes file.
1634
+ # Loads another routes file with the given `name` located inside the
1635
+ # `config/routes` directory. In that file, you can use the normal routing DSL,
1636
+ # but *do not* surround it with a `Rails.application.routes.draw` block.
1637
+ #
1638
+ # # config/routes.rb
1639
+ # Rails.application.routes.draw do
1640
+ # draw :admin # Loads `config/routes/admin.rb`
1641
+ # draw "third_party/some_gem" # Loads `config/routes/third_party/some_gem.rb`
1642
+ # end
1643
+ #
1644
+ # # config/routes/admin.rb
1645
+ # namespace :admin do
1646
+ # resources :accounts
1647
+ # end
1648
+ #
1649
+ # # config/routes/third_party/some_gem.rb
1650
+ # mount SomeGem::Engine, at: "/some_gem"
1651
+ #
1652
+ # **CAUTION:** Use this feature with care. Having multiple routes files can
1653
+ # negatively impact discoverability and readability. For most applications —
1654
+ # even those with a few hundred routes it's easier for developers to have a
1655
+ # single routes file.
1621
1656
  def draw(name)
1622
1657
  path = @draw_paths.find do |_path|
1623
1658
  File.exist? "#{_path}/#{name}.rb"
@@ -1634,12 +1669,12 @@ module ActionDispatch
1634
1669
  instance_eval(File.read(route_path), route_path.to_s)
1635
1670
  end
1636
1671
 
1637
- # Matches a URL pattern to one or more routes.
1638
- # For more information, see match[rdoc-ref:Base#match].
1672
+ # Matches a URL pattern to one or more routes. For more information, see
1673
+ # [match](rdoc-ref:Base#match).
1639
1674
  #
1640
- # match 'path' => 'controller#action', via: :patch
1641
- # match 'path', to: 'controller#action', via: :post
1642
- # match 'path', 'otherpath', on: :member, via: :get
1675
+ # match 'path' => 'controller#action', via: :patch
1676
+ # match 'path', to: 'controller#action', via: :post
1677
+ # match 'path', 'otherpath', on: :member, via: :get
1643
1678
  def match(path, *rest, &block)
1644
1679
  if rest.empty? && Hash === path
1645
1680
  options = path
@@ -1674,19 +1709,19 @@ module ActionDispatch
1674
1709
  end
1675
1710
  end
1676
1711
 
1677
- # You can specify what \Rails should route "/" to with the root method:
1712
+ # You can specify what Rails should route "/" to with the root method:
1678
1713
  #
1679
- # root to: 'pages#main'
1714
+ # root to: 'pages#main'
1680
1715
  #
1681
- # For options, see +match+, as +root+ uses it internally.
1716
+ # For options, see `match`, as `root` uses it internally.
1682
1717
  #
1683
1718
  # You can also pass a string which will expand
1684
1719
  #
1685
- # root 'pages#main'
1720
+ # root 'pages#main'
1686
1721
  #
1687
- # You should put the root route at the top of <tt>config/routes.rb</tt>,
1688
- # because this means it will be matched first. As this is the most popular route
1689
- # of most \Rails applications, this is beneficial.
1722
+ # You should put the root route at the top of `config/routes.rb`, because this
1723
+ # means it will be matched first. As this is the most popular route of most
1724
+ # Rails applications, this is beneficial.
1690
1725
  def root(path, options = {})
1691
1726
  if path.is_a?(String)
1692
1727
  options[:to] = path
@@ -1864,9 +1899,9 @@ module ActionDispatch
1864
1899
  candidate = action_name.select(&:present?).join("_")
1865
1900
 
1866
1901
  unless candidate.empty?
1867
- # If a name was not explicitly given, we check if it is valid
1868
- # and return nil in case it isn't. Otherwise, we pass the invalid name
1869
- # forward so the underlying router engine treats it and raises an exception.
1902
+ # If a name was not explicitly given, we check if it is valid and return nil in
1903
+ # case it isn't. Otherwise, we pass the invalid name forward so the underlying
1904
+ # router engine treats it and raises an exception.
1870
1905
  if as.nil?
1871
1906
  candidate unless !candidate.match?(/\A[_a-z]/i) || has_named_route?(candidate)
1872
1907
  else
@@ -2002,83 +2037,81 @@ module ActionDispatch
2002
2037
  end
2003
2038
  end
2004
2039
 
2005
- # Routing Concerns allow you to declare common routes that can be reused
2006
- # inside others resources and routes.
2040
+ # Routing Concerns allow you to declare common routes that can be reused inside
2041
+ # others resources and routes.
2007
2042
  #
2008
- # concern :commentable do
2009
- # resources :comments
2010
- # end
2043
+ # concern :commentable do
2044
+ # resources :comments
2045
+ # end
2011
2046
  #
2012
- # concern :image_attachable do
2013
- # resources :images, only: :index
2014
- # end
2047
+ # concern :image_attachable do
2048
+ # resources :images, only: :index
2049
+ # end
2015
2050
  #
2016
2051
  # These concerns are used in Resources routing:
2017
2052
  #
2018
- # resources :messages, concerns: [:commentable, :image_attachable]
2053
+ # resources :messages, concerns: [:commentable, :image_attachable]
2019
2054
  #
2020
2055
  # or in a scope or namespace:
2021
2056
  #
2022
- # namespace :posts do
2023
- # concerns :commentable
2024
- # end
2057
+ # namespace :posts do
2058
+ # concerns :commentable
2059
+ # end
2025
2060
  module Concerns
2026
2061
  # Define a routing concern using a name.
2027
2062
  #
2028
- # Concerns may be defined inline, using a block, or handled by
2029
- # another object, by passing that object as the second parameter.
2063
+ # Concerns may be defined inline, using a block, or handled by another object,
2064
+ # by passing that object as the second parameter.
2030
2065
  #
2031
- # The concern object, if supplied, should respond to <tt>call</tt>,
2032
- # which will receive two parameters:
2066
+ # The concern object, if supplied, should respond to `call`, which will receive
2067
+ # two parameters:
2033
2068
  #
2034
- # * The current mapper
2035
- # * A hash of options which the concern object may use
2069
+ # * The current mapper
2070
+ # * A hash of options which the concern object may use
2036
2071
  #
2037
- # Options may also be used by concerns defined in a block by accepting
2038
- # a block parameter. So, using a block, you might do something as
2039
- # simple as limit the actions available on certain resources, passing
2040
- # standard resource options through the concern:
2072
+ # Options may also be used by concerns defined in a block by accepting a block
2073
+ # parameter. So, using a block, you might do something as simple as limit the
2074
+ # actions available on certain resources, passing standard resource options
2075
+ # through the concern:
2041
2076
  #
2042
- # concern :commentable do |options|
2043
- # resources :comments, options
2044
- # end
2077
+ # concern :commentable do |options|
2078
+ # resources :comments, options
2079
+ # end
2045
2080
  #
2046
- # resources :posts, concerns: :commentable
2047
- # resources :archived_posts do
2048
- # # Don't allow comments on archived posts
2049
- # concerns :commentable, only: [:index, :show]
2050
- # end
2081
+ # resources :posts, concerns: :commentable
2082
+ # resources :archived_posts do
2083
+ # # Don't allow comments on archived posts
2084
+ # concerns :commentable, only: [:index, :show]
2085
+ # end
2051
2086
  #
2052
- # Or, using a callable object, you might implement something more
2053
- # specific to your application, which would be out of place in your
2054
- # routes file.
2087
+ # Or, using a callable object, you might implement something more specific to
2088
+ # your application, which would be out of place in your routes file.
2055
2089
  #
2056
- # # purchasable.rb
2057
- # class Purchasable
2058
- # def initialize(defaults = {})
2059
- # @defaults = defaults
2060
- # end
2090
+ # # purchasable.rb
2091
+ # class Purchasable
2092
+ # def initialize(defaults = {})
2093
+ # @defaults = defaults
2094
+ # end
2061
2095
  #
2062
- # def call(mapper, options = {})
2063
- # options = @defaults.merge(options)
2064
- # mapper.resources :purchases
2065
- # mapper.resources :receipts
2066
- # mapper.resources :returns if options[:returnable]
2096
+ # def call(mapper, options = {})
2097
+ # options = @defaults.merge(options)
2098
+ # mapper.resources :purchases
2099
+ # mapper.resources :receipts
2100
+ # mapper.resources :returns if options[:returnable]
2101
+ # end
2067
2102
  # end
2068
- # end
2069
2103
  #
2070
- # # routes.rb
2071
- # concern :purchasable, Purchasable.new(returnable: true)
2104
+ # # routes.rb
2105
+ # concern :purchasable, Purchasable.new(returnable: true)
2072
2106
  #
2073
- # resources :toys, concerns: :purchasable
2074
- # resources :electronics, concerns: :purchasable
2075
- # resources :pets do
2076
- # concerns :purchasable, returnable: false
2077
- # end
2107
+ # resources :toys, concerns: :purchasable
2108
+ # resources :electronics, concerns: :purchasable
2109
+ # resources :pets do
2110
+ # concerns :purchasable, returnable: false
2111
+ # end
2078
2112
  #
2079
- # Any routing helpers can be used inside a concern. If using a
2080
- # callable, they're accessible from the Mapper that's passed to
2081
- # <tt>call</tt>.
2113
+ # Any routing helpers can be used inside a concern. If using a callable, they're
2114
+ # accessible from the Mapper that's passed to `call`.
2082
2115
  def concern(name, callable = nil, &block)
2083
2116
  callable ||= lambda { |mapper, options| mapper.instance_exec(options, &block) }
2084
2117
  @concerns[name] = callable
@@ -2086,15 +2119,15 @@ module ActionDispatch
2086
2119
 
2087
2120
  # Use the named concerns
2088
2121
  #
2089
- # resources :posts do
2090
- # concerns :commentable
2091
- # end
2122
+ # resources :posts do
2123
+ # concerns :commentable
2124
+ # end
2092
2125
  #
2093
2126
  # Concerns also work in any routes helper that you want to use:
2094
2127
  #
2095
- # namespace :posts do
2096
- # concerns :commentable
2097
- # end
2128
+ # namespace :posts do
2129
+ # concerns :commentable
2130
+ # end
2098
2131
  def concerns(*args)
2099
2132
  options = args.extract_options!
2100
2133
  args.flatten.each do |name|
@@ -2108,53 +2141,55 @@ module ActionDispatch
2108
2141
  end
2109
2142
 
2110
2143
  module CustomUrls
2111
- # Define custom URL helpers that will be added to the application's
2112
- # routes. This allows you to override and/or replace the default behavior
2113
- # of routing helpers, e.g:
2144
+ # Define custom URL helpers that will be added to the application's routes. This
2145
+ # allows you to override and/or replace the default behavior of routing helpers,
2146
+ # e.g:
2114
2147
  #
2115
- # direct :homepage do
2116
- # "https://rubyonrails.org"
2117
- # end
2148
+ # direct :homepage do
2149
+ # "https://rubyonrails.org"
2150
+ # end
2118
2151
  #
2119
- # direct :commentable do |model|
2120
- # [ model, anchor: model.dom_id ]
2121
- # end
2152
+ # direct :commentable do |model|
2153
+ # [ model, anchor: model.dom_id ]
2154
+ # end
2122
2155
  #
2123
- # direct :main do
2124
- # { controller: "pages", action: "index", subdomain: "www" }
2125
- # end
2156
+ # direct :main do
2157
+ # { controller: "pages", action: "index", subdomain: "www" }
2158
+ # end
2126
2159
  #
2127
- # The return value from the block passed to +direct+ must be a valid set of
2128
- # arguments for +url_for+ which will actually build the URL string. This can
2129
- # be one of the following:
2160
+ # The return value from the block passed to `direct` must be a valid set of
2161
+ # arguments for `url_for` which will actually build the URL string. This can be
2162
+ # one of the following:
2130
2163
  #
2131
- # * A string, which is treated as a generated URL
2132
- # * A hash, e.g. <tt>{ controller: "pages", action: "index" }</tt>
2133
- # * An array, which is passed to +polymorphic_url+
2134
- # * An Active Model instance
2135
- # * An Active Model class
2164
+ # * A string, which is treated as a generated URL
2165
+ # * A hash, e.g. `{ controller: "pages", action: "index" }`
2166
+ # * An array, which is passed to `polymorphic_url`
2167
+ # * An Active Model instance
2168
+ # * An Active Model class
2136
2169
  #
2137
- # NOTE: Other URL helpers can be called in the block but be careful not to invoke
2138
- # your custom URL helper again otherwise it will result in a stack overflow error.
2139
2170
  #
2140
- # You can also specify default options that will be passed through to
2141
- # your URL helper definition, e.g:
2171
+ # NOTE: Other URL helpers can be called in the block but be careful not to
2172
+ # invoke your custom URL helper again otherwise it will result in a stack
2173
+ # overflow error.
2142
2174
  #
2143
- # direct :browse, page: 1, size: 10 do |options|
2144
- # [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
2145
- # end
2175
+ # You can also specify default options that will be passed through to your URL
2176
+ # helper definition, e.g:
2146
2177
  #
2147
- # In this instance the +params+ object comes from the context in which the
2148
- # block is executed, e.g. generating a URL inside a controller action or a view.
2149
- # If the block is executed where there isn't a +params+ object such as this:
2178
+ # direct :browse, page: 1, size: 10 do |options|
2179
+ # [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
2180
+ # end
2150
2181
  #
2151
- # Rails.application.routes.url_helpers.browse_path
2182
+ # In this instance the `params` object comes from the context in which the block
2183
+ # is executed, e.g. generating a URL inside a controller action or a view. If
2184
+ # the block is executed where there isn't a `params` object such as this:
2152
2185
  #
2153
- # then it will raise a +NameError+. Because of this you need to be aware of the
2186
+ # Rails.application.routes.url_helpers.browse_path
2187
+ #
2188
+ # then it will raise a `NameError`. Because of this you need to be aware of the
2154
2189
  # context in which you will use your custom URL helper when defining it.
2155
2190
  #
2156
- # NOTE: The +direct+ method can't be used inside of a scope block such as
2157
- # +namespace+ or +scope+ and will raise an error if it detects that it is.
2191
+ # NOTE: The `direct` method can't be used inside of a scope block such as
2192
+ # `namespace` or `scope` and will raise an error if it detects that it is.
2158
2193
  def direct(name, options = {}, &block)
2159
2194
  unless @scope.root?
2160
2195
  raise RuntimeError, "The direct method can't be used inside a routes scope block"
@@ -2163,50 +2198,50 @@ module ActionDispatch
2163
2198
  @set.add_url_helper(name, options, &block)
2164
2199
  end
2165
2200
 
2166
- # Define custom polymorphic mappings of models to URLs. This alters the
2167
- # behavior of +polymorphic_url+ and consequently the behavior of
2168
- # +link_to+ and +form_for+ when passed a model instance, e.g:
2201
+ # Define custom polymorphic mappings of models to URLs. This alters the behavior
2202
+ # of `polymorphic_url` and consequently the behavior of `link_to` and `form_for`
2203
+ # when passed a model instance, e.g:
2169
2204
  #
2170
- # resource :basket
2205
+ # resource :basket
2171
2206
  #
2172
- # resolve "Basket" do
2173
- # [:basket]
2174
- # end
2207
+ # resolve "Basket" do
2208
+ # [:basket]
2209
+ # end
2175
2210
  #
2176
- # This will now generate "/basket" when a +Basket+ instance is passed to
2177
- # +link_to+ or +form_for+ instead of the standard "/baskets/:id".
2211
+ # This will now generate "/basket" when a `Basket` instance is passed to
2212
+ # `link_to` or `form_for` instead of the standard "/baskets/:id".
2178
2213
  #
2179
- # NOTE: This custom behavior only applies to simple polymorphic URLs where
2180
- # a single model instance is passed and not more complicated forms, e.g:
2214
+ # NOTE: This custom behavior only applies to simple polymorphic URLs where a
2215
+ # single model instance is passed and not more complicated forms, e.g:
2181
2216
  #
2182
- # # config/routes.rb
2183
- # resource :profile
2184
- # namespace :admin do
2185
- # resources :users
2186
- # end
2217
+ # # config/routes.rb
2218
+ # resource :profile
2219
+ # namespace :admin do
2220
+ # resources :users
2221
+ # end
2187
2222
  #
2188
- # resolve("User") { [:profile] }
2223
+ # resolve("User") { [:profile] }
2189
2224
  #
2190
- # # app/views/application/_menu.html.erb
2191
- # link_to "Profile", @current_user
2192
- # link_to "Profile", [:admin, @current_user]
2225
+ # # app/views/application/_menu.html.erb
2226
+ # link_to "Profile", @current_user
2227
+ # link_to "Profile", [:admin, @current_user]
2193
2228
  #
2194
- # The first +link_to+ will generate "/profile" but the second will generate
2195
- # the standard polymorphic URL of "/admin/users/1".
2229
+ # The first `link_to` will generate "/profile" but the second will generate the
2230
+ # standard polymorphic URL of "/admin/users/1".
2196
2231
  #
2197
- # You can pass options to a polymorphic mapping - the arity for the block
2198
- # needs to be two as the instance is passed as the first argument, e.g:
2232
+ # You can pass options to a polymorphic mapping - the arity for the block needs
2233
+ # to be two as the instance is passed as the first argument, e.g:
2199
2234
  #
2200
- # resolve "Basket", anchor: "items" do |basket, options|
2201
- # [:basket, options]
2202
- # end
2235
+ # resolve "Basket", anchor: "items" do |basket, options|
2236
+ # [:basket, options]
2237
+ # end
2203
2238
  #
2204
- # This generates the URL "/basket#items" because when the last item in an
2205
- # array passed to +polymorphic_url+ is a hash then it's treated as options
2206
- # to the URL helper that gets called.
2239
+ # This generates the URL "/basket#items" because when the last item in an array
2240
+ # passed to `polymorphic_url` is a hash then it's treated as options to the URL
2241
+ # helper that gets called.
2207
2242
  #
2208
- # NOTE: The +resolve+ method can't be used inside of a scope block such as
2209
- # +namespace+ or +scope+ and will raise an error if it detects that it is.
2243
+ # NOTE: The `resolve` method can't be used inside of a scope block such as
2244
+ # `namespace` or `scope` and will raise an error if it detects that it is.
2210
2245
  def resolve(*args, &block)
2211
2246
  unless @scope.root?
2212
2247
  raise RuntimeError, "The resolve method can't be used inside a routes scope block"