actionpack 7.1.5.1 → 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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -642
  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 +12 -13
  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 +214 -203
  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 +483 -478
  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 +5 -1
  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 +48 -59
  69. data/lib/action_dispatch/http/filter_parameters.rb +13 -14
  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 +25 -21
  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 +26 -36
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +75 -95
  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 +2 -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 +16 -16
  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/routes/_table.html.erb +1 -1
  125. data/lib/action_dispatch/railtie.rb +2 -3
  126. data/lib/action_dispatch/request/session.rb +23 -21
  127. data/lib/action_dispatch/request/utils.rb +2 -0
  128. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  129. data/lib/action_dispatch/routing/inspector.rb +6 -4
  130. data/lib/action_dispatch/routing/mapper.rb +623 -625
  131. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  132. data/lib/action_dispatch/routing/redirection.rb +37 -32
  133. data/lib/action_dispatch/routing/route_set.rb +60 -46
  134. data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
  135. data/lib/action_dispatch/routing/url_for.rb +130 -125
  136. data/lib/action_dispatch/routing.rb +150 -148
  137. data/lib/action_dispatch/system_test_case.rb +91 -81
  138. data/lib/action_dispatch/system_testing/browser.rb +4 -2
  139. data/lib/action_dispatch/system_testing/driver.rb +2 -0
  140. data/lib/action_dispatch/system_testing/server.rb +2 -0
  141. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
  142. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  143. data/lib/action_dispatch/testing/assertion_response.rb +8 -6
  144. data/lib/action_dispatch/testing/assertions/response.rb +26 -23
  145. data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
  146. data/lib/action_dispatch/testing/assertions.rb +2 -0
  147. data/lib/action_dispatch/testing/integration.rb +223 -222
  148. data/lib/action_dispatch/testing/request_encoder.rb +2 -0
  149. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  150. data/lib/action_dispatch/testing/test_process.rb +12 -8
  151. data/lib/action_dispatch/testing/test_request.rb +3 -1
  152. data/lib/action_dispatch/testing/test_response.rb +27 -26
  153. data/lib/action_dispatch.rb +22 -32
  154. data/lib/action_pack/gem_version.rb +6 -4
  155. data/lib/action_pack/version.rb +3 -1
  156. data/lib/action_pack.rb +17 -16
  157. metadata +33 -16
@@ -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"
@@ -31,10 +33,10 @@ module ActionDispatch
31
33
  CALL = ->(app, req) { app.call req.env }
32
34
 
33
35
  def initialize(app, constraints, strategy)
34
- # Unwrap Constraints objects. I don't actually think it's possible
35
- # to pass a Constraints object to this constructor, but there were
36
- # multiple places that kept testing children of this object. I
37
- # *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.
38
40
  if app.is_a?(self.class)
39
41
  constraints += app.constraints
40
42
  app = app.app
@@ -219,7 +221,7 @@ module ActionDispatch
219
221
  # Add a default constraint for :controller path segments that matches namespaced
220
222
  # controllers with default routes like :controller/:action/:id(.:format), e.g:
221
223
  # GET /admin/products/show/1
222
- # => { controller: 'admin/products', action: 'show', id: '1' }
224
+ # # > { controller: 'admin/products', action: 'show', id: '1' }
223
225
  options[:controller] ||= /.+?/
224
226
  end
225
227
 
@@ -406,22 +408,20 @@ module ActionDispatch
406
408
  end
407
409
  end
408
410
 
409
- # Invokes Journey::Router::Utils.normalize_path, then ensures that
410
- # /(:locale) becomes (/:locale). Except for root cases, where the
411
- # 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.
412
414
  def self.normalize_path(path)
413
415
  path = Journey::Router::Utils.normalize_path(path)
414
416
 
415
417
  # the path for a root URL at this point can be something like
416
418
  # "/(/:locale)(/:platform)/(:browser)", and we would want
417
- # "/(:locale)(/:platform)(/:browser)"
418
-
419
- # reverse "/(", "/((" etc to "(/", "((/" etc
419
+ # "/(:locale)(/:platform)(/:browser)" reverse "/(", "/((" etc to "(/", "((/" etc
420
420
  path.gsub!(%r{/(\(+)/?}, '\1/')
421
- # if a path is all optional segments, change the leading "(/" back to
422
- # "/(" so it evaluates to "/" when interpreted with no options.
423
- # Unless, however, at least one secondary segment consists of a static
424
- # 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)"
425
425
  path.sub!(%r{^(\(+)/}, '/\1') if %r{^(\(+[^)]+\))(\(+/:[^)]+\))*$}.match?(path)
426
426
  path
427
427
  end
@@ -433,206 +433,202 @@ module ActionDispatch
433
433
  module Base
434
434
  # Matches a URL pattern to one or more routes.
435
435
  #
436
- # You should not use the +match+ method in your router
437
- # without specifying an HTTP method.
436
+ # You should not use the `match` method in your router without specifying an
437
+ # HTTP method.
438
438
  #
439
439
  # If you want to expose your action to both GET and POST, use:
440
440
  #
441
- # # sets :controller, :action, and :id in params
442
- # match ':controller/:action/:id', via: [:get, :post]
441
+ # # sets :controller, :action, and :id in params
442
+ # match ':controller/:action/:id', via: [:get, :post]
443
443
  #
444
- # Note that +:controller+, +:action+, and +:id+ are interpreted as URL
445
- # 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.
446
446
  #
447
- # 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:
448
448
  #
449
449
  # Instead of:
450
450
  #
451
- # match ":controller/:action/:id"
451
+ # match ":controller/:action/:id"
452
452
  #
453
453
  # Do:
454
454
  #
455
- # get ":controller/:action/:id"
455
+ # get ":controller/:action/:id"
456
456
  #
457
- # Two of these symbols are special, +:controller+ maps to the controller
458
- # and +:action+ to the controller's action. A pattern can also map
459
- # 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:
460
460
  #
461
- # get 'songs/*category/:title', to: 'songs#show'
461
+ # get 'songs/*category/:title', to: 'songs#show'
462
462
  #
463
- # # 'songs/rock/classic/stairway-to-heaven' sets
464
- # # params[:category] = 'rock/classic'
465
- # # params[:title] = 'stairway-to-heaven'
463
+ # # 'songs/rock/classic/stairway-to-heaven' sets
464
+ # # params[:category] = 'rock/classic'
465
+ # # params[:title] = 'stairway-to-heaven'
466
466
  #
467
- # To match a wildcard parameter, it must have a name assigned to it.
468
- # Without a variable name to attach the glob parameter to, the route
469
- # 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.
470
469
  #
471
- # When a pattern points to an internal route, the route's +:action+ and
472
- # +: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:
473
472
  #
474
- # match 'photos/:id' => 'photos#show', via: :get
475
- # match 'photos/:id', to: 'photos#show', via: :get
476
- # 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
477
476
  #
478
- # A pattern can also point to a +Rack+ endpoint i.e. anything that
479
- # responds to +call+:
477
+ # A pattern can also point to a `Rack` endpoint i.e. anything that responds to
478
+ # `call`:
480
479
  #
481
- # match 'photos/:id', to: -> (hash) { [200, {}, ["Coming soon"]] }, via: :get
482
- # match 'photos/:id', to: PhotoRackApp, via: :get
483
- # # Yes, controller actions are just rack endpoints
484
- # 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
485
484
  #
486
485
  # Because requesting various HTTP verbs with a single action has security
487
- # implications, you must either specify the actions in
488
- # the via options or use one of the HttpHelpers[rdoc-ref:HttpHelpers]
489
- # 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`
490
488
  #
491
- # === Options
489
+ # ### Options
492
490
  #
493
491
  # Any options not seen here are passed on as params with the URL.
494
492
  #
495
- # [:controller]
496
- # The route's controller.
493
+ # :controller
494
+ # : The route's controller.
497
495
  #
498
- # [:action]
499
- # The route's action.
496
+ # :action
497
+ # : The route's action.
500
498
  #
501
- # [:param]
502
- # Overrides the default resource identifier +:id+ (name of the
503
- # dynamic segment used to generate the routes).
504
- # You can access that segment from your controller using
505
- # <tt>params[<:param>]</tt>.
506
- # 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:
507
503
  #
508
- # resources :users, param: :name
504
+ # resources :users, param: :name
509
505
  #
510
- # 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:
511
507
  #
512
- # GET /users(.:format)
513
- # POST /users(.:format)
514
- # GET /users/new(.:format)
515
- # GET /users/:name/edit(.:format)
516
- # GET /users/:name(.:format)
517
- # PATCH/PUT /users/:name(.:format)
518
- # 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)
519
515
  #
520
- # You can override <tt>ActiveRecord::Base#to_param</tt> of a related
521
- # model to construct a URL:
516
+ # You can override `ActiveRecord::Base#to_param` of a related model to
517
+ # construct a URL:
522
518
  #
523
- # class User < ActiveRecord::Base
524
- # def to_param
525
- # name
526
- # end
527
- # end
519
+ # class User < ActiveRecord::Base
520
+ # def to_param
521
+ # name
522
+ # end
523
+ # end
528
524
  #
529
- # user = User.find_by(name: 'Phusion')
530
- # user_path(user) # => "/users/Phusion"
525
+ # user = User.find_by(name: 'Phusion')
526
+ # user_path(user) # => "/users/Phusion"
531
527
  #
532
- # [:path]
533
- # The path prefix for the routes.
528
+ # :path
529
+ # : The path prefix for the routes.
534
530
  #
535
- # [:module]
536
- # The namespace for :controller.
531
+ # :module
532
+ # : The namespace for :controller.
537
533
  #
538
- # match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: :get
539
- # # => Sekret::PostsController
534
+ # match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: :get
535
+ # # => Sekret::PostsController
540
536
  #
541
- # See <tt>Scoping#namespace</tt> for its scope equivalent.
537
+ # See `Scoping#namespace` for its scope equivalent.
542
538
  #
543
- # [:as]
544
- # The name used to generate routing helpers.
539
+ # :as
540
+ # : The name used to generate routing helpers.
545
541
  #
546
- # [:via]
547
- # Allowed HTTP verb(s) for route.
542
+ # :via
543
+ # : Allowed HTTP verb(s) for route.
548
544
  #
549
- # match 'path', to: 'c#a', via: :get
550
- # match 'path', to: 'c#a', via: [:get, :post]
551
- # 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
552
548
  #
553
- # [:to]
554
- # Points to a +Rack+ endpoint. Can be an object that responds to
555
- # +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.
556
552
  #
557
- # match 'path', to: 'controller#action', via: :get
558
- # match 'path', to: -> (env) { [200, {}, ["Success!"]] }, via: :get
559
- # 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
560
556
  #
561
- # [:on]
562
- # Shorthand for wrapping routes in a specific RESTful context. Valid
563
- # values are +:member+, +:collection+, and +:new+. Only use within
564
- # <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:
565
561
  #
566
- # resource :bar do
567
- # match 'foo', to: 'c#a', on: :member, via: [:get, :post]
568
- # end
562
+ # resource :bar do
563
+ # match 'foo', to: 'c#a', on: :member, via: [:get, :post]
564
+ # end
569
565
  #
570
- # Is equivalent to:
566
+ # Is equivalent to:
571
567
  #
572
- # resource :bar do
573
- # member do
574
- # match 'foo', to: 'c#a', via: [:get, :post]
575
- # end
576
- # end
568
+ # resource :bar do
569
+ # member do
570
+ # match 'foo', to: 'c#a', via: [:get, :post]
571
+ # end
572
+ # end
577
573
  #
578
- # [:constraints]
579
- # Constrains parameters with a hash of regular expressions
580
- # or an object that responds to <tt>matches?</tt>. In addition, constraints
581
- # other than path can also be specified with any object
582
- # 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.).
583
579
  #
584
- # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :get
580
+ # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :get
585
581
  #
586
- # match 'json_only', constraints: { format: 'json' }, via: :get
582
+ # match 'json_only', constraints: { format: 'json' }, via: :get
587
583
  #
588
- # class PermitList
589
- # def matches?(request) request.remote_ip == '1.2.3.4' end
590
- # end
591
- # 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
588
+ #
589
+ # See `Scoping#constraints` for more examples with its scope equivalent.
592
590
  #
593
- # See <tt>Scoping#constraints</tt> for more examples with its scope
594
- # equivalent.
591
+ # :defaults
592
+ # : Sets defaults for parameters
595
593
  #
596
- # [:defaults]
597
- # Sets defaults for parameters
594
+ # # Sets params[:format] to 'jpg' by default
595
+ # match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: :get
598
596
  #
599
- # # Sets params[:format] to 'jpg' by default
600
- # match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: :get
597
+ # See `Scoping#defaults` for its scope equivalent.
601
598
  #
602
- # See <tt>Scoping#defaults</tt> for its scope equivalent.
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.
603
602
  #
604
- # [:anchor]
605
- # Boolean to anchor a <tt>match</tt> pattern. Default is true. When set to
606
- # false, the pattern matches any request prefixed with the given path.
603
+ # # Matches any request starting with 'path'
604
+ # match 'path', to: 'c#a', anchor: false, via: :get
607
605
  #
608
- # # Matches any request starting with 'path'
609
- # match 'path', to: 'c#a', anchor: false, via: :get
606
+ # :format
607
+ # : Allows you to specify the default value for optional `format` segment or
608
+ # disable it by supplying `false`.
610
609
  #
611
- # [:format]
612
- # Allows you to specify the default value for optional +format+
613
- # segment or disable it by supplying +false+.
614
610
  def match(path, options = nil)
615
611
  end
616
612
 
617
613
  # Mount a Rack-based application to be used within the application.
618
614
  #
619
- # mount SomeRackApp, at: "some_route"
615
+ # mount SomeRackApp, at: "some_route"
620
616
  #
621
617
  # Alternatively:
622
618
  #
623
- # mount(SomeRackApp => "some_route")
619
+ # mount(SomeRackApp => "some_route")
624
620
  #
625
- # For options, see +match+, as +mount+ uses it internally.
621
+ # For options, see `match`, as `mount` uses it internally.
626
622
  #
627
- # All mounted applications come with routing helpers to access them.
628
- # These are named after the class specified, so for the above example
629
- # the helper is either +some_rack_app_path+ or +some_rack_app_url+.
630
- # 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:
631
627
  #
632
- # mount(SomeRackApp => "some_route", as: "exciting")
628
+ # mount(SomeRackApp => "some_route", as: "exciting")
633
629
  #
634
- # This will generate the +exciting_path+ and +exciting_url+ helpers
635
- # 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.
636
632
  def mount(app, options = nil)
637
633
  if options
638
634
  path = options.delete(:at)
@@ -706,7 +702,8 @@ module ActionDispatch
706
702
  prefix_options.reverse_merge!(options[:_recall].slice(*_route.segment_keys))
707
703
  end
708
704
 
709
- # 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.
710
707
  _route.segment_keys.each { |k| options.delete(k) }
711
708
  _url_helpers.public_send("#{name}_path", prefix_options)
712
709
  end
@@ -717,7 +714,7 @@ module ActionDispatch
717
714
  def optimize_routes_generation?; false; end
718
715
 
719
716
  define_method :find_script_name do |options|
720
- if options.key?(:script_name) && options[:script_name].present?
717
+ if options.key? :script_name
721
718
  super(options)
722
719
  else
723
720
  script_namer.call(options)
@@ -728,50 +725,50 @@ module ActionDispatch
728
725
  end
729
726
 
730
727
  module HttpHelpers
731
- # Define a route that only recognizes HTTP GET.
732
- # 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)
733
730
  #
734
- # get 'bacon', to: 'food#bacon'
731
+ # get 'bacon', to: 'food#bacon'
735
732
  def get(*args, &block)
736
733
  map_method(:get, args, &block)
737
734
  end
738
735
 
739
- # Define a route that only recognizes HTTP POST.
740
- # 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)
741
738
  #
742
- # post 'bacon', to: 'food#bacon'
739
+ # post 'bacon', to: 'food#bacon'
743
740
  def post(*args, &block)
744
741
  map_method(:post, args, &block)
745
742
  end
746
743
 
747
- # Define a route that only recognizes HTTP PATCH.
748
- # 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)
749
746
  #
750
- # patch 'bacon', to: 'food#bacon'
747
+ # patch 'bacon', to: 'food#bacon'
751
748
  def patch(*args, &block)
752
749
  map_method(:patch, args, &block)
753
750
  end
754
751
 
755
- # Define a route that only recognizes HTTP PUT.
756
- # 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)
757
754
  #
758
- # put 'bacon', to: 'food#bacon'
755
+ # put 'bacon', to: 'food#bacon'
759
756
  def put(*args, &block)
760
757
  map_method(:put, args, &block)
761
758
  end
762
759
 
763
- # Define a route that only recognizes HTTP DELETE.
764
- # 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)
765
762
  #
766
- # delete 'broccoli', to: 'food#broccoli'
763
+ # delete 'broccoli', to: 'food#broccoli'
767
764
  def delete(*args, &block)
768
765
  map_method(:delete, args, &block)
769
766
  end
770
767
 
771
- # Define a route that only recognizes HTTP OPTIONS.
772
- # 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)
773
770
  #
774
- # options 'carrots', to: 'food#carrots'
771
+ # options 'carrots', to: 'food#carrots'
775
772
  def options(*args, &block)
776
773
  map_method(:options, args, &block)
777
774
  end
@@ -785,91 +782,90 @@ module ActionDispatch
785
782
  end
786
783
  end
787
784
 
788
- # You may wish to organize groups of controllers under a namespace.
789
- # Most commonly, you might group a number of administrative controllers
790
- # under an +admin+ namespace. You would place these controllers under
791
- # the <tt>app/controllers/admin</tt> directory, and you can group them
792
- # 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:
793
790
  #
794
- # namespace "admin" do
795
- # resources :posts, :comments
796
- # end
791
+ # namespace "admin" do
792
+ # resources :posts, :comments
793
+ # end
797
794
  #
798
795
  # This will create a number of routes for each of the posts and comments
799
- # controller. For +Admin::PostsController+, \Rails will create:
796
+ # controller. For `Admin::PostsController`, Rails will create:
800
797
  #
801
- # GET /admin/posts
802
- # GET /admin/posts/new
803
- # POST /admin/posts
804
- # GET /admin/posts/1
805
- # GET /admin/posts/1/edit
806
- # PATCH/PUT /admin/posts/1
807
- # 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
808
805
  #
809
806
  # If you want to route /posts (without the prefix /admin) to
810
- # +Admin::PostsController+, you could use
807
+ # `Admin::PostsController`, you could use
811
808
  #
812
- # scope module: "admin" do
813
- # resources :posts
814
- # end
809
+ # scope module: "admin" do
810
+ # resources :posts
811
+ # end
815
812
  #
816
813
  # or, for a single case
817
814
  #
818
- # resources :posts, module: "admin"
815
+ # resources :posts, module: "admin"
819
816
  #
820
- # If you want to route /admin/posts to +PostsController+
821
- # (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
822
819
  #
823
- # scope "/admin" do
824
- # resources :posts
825
- # end
820
+ # scope "/admin" do
821
+ # resources :posts
822
+ # end
826
823
  #
827
824
  # or, for a single case
828
825
  #
829
- # resources :posts, path: "/admin/posts"
826
+ # resources :posts, path: "/admin/posts"
830
827
  #
831
- # In each of these cases, the named routes remain the same as if you did
832
- # not use scope. In the last case, the following paths map to
833
- # +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`:
834
830
  #
835
- # GET /admin/posts
836
- # GET /admin/posts/new
837
- # POST /admin/posts
838
- # GET /admin/posts/1
839
- # GET /admin/posts/1/edit
840
- # PATCH/PUT /admin/posts/1
841
- # 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
842
838
  module Scoping
843
839
  # Scopes a set of routes to the given default options.
844
840
  #
845
841
  # Take the following route definition as an example:
846
842
  #
847
- # scope path: ":account_id", as: "account" do
848
- # resources :projects
849
- # end
843
+ # scope path: ":account_id", as: "account" do
844
+ # resources :projects
845
+ # end
850
846
  #
851
- # This generates helpers such as +account_projects_path+, just like +resources+ does.
852
- # The difference here being that the routes generated are like /:account_id/projects,
853
- # 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.
854
850
  #
855
- # === Options
851
+ # ### Options
856
852
  #
857
- # Takes same options as <tt>Base#match</tt> and <tt>Resources#resources</tt>.
853
+ # Takes same options as `Base#match` and `Resources#resources`.
858
854
  #
859
- # # route /posts (without the prefix /admin) to +Admin::PostsController+
860
- # scope module: "admin" do
861
- # resources :posts
862
- # end
855
+ # # route /posts (without the prefix /admin) to +Admin::PostsController+
856
+ # scope module: "admin" do
857
+ # resources :posts
858
+ # end
863
859
  #
864
- # # prefix the posts resource's requests with '/admin'
865
- # scope path: "/admin" do
866
- # resources :posts
867
- # end
860
+ # # prefix the posts resource's requests with '/admin'
861
+ # scope path: "/admin" do
862
+ # resources :posts
863
+ # end
868
864
  #
869
- # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
870
- # scope as: "sekret" do
871
- # resources :posts
872
- # end
865
+ # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
866
+ # scope as: "sekret" do
867
+ # resources :posts
868
+ # end
873
869
  def scope(*args)
874
870
  options = args.extract_options!.dup
875
871
  scope = {}
@@ -926,9 +922,9 @@ module ActionDispatch
926
922
 
927
923
  # Scopes routes to a specific controller
928
924
  #
929
- # controller "food" do
930
- # match "bacon", action: :bacon, via: :get
931
- # end
925
+ # controller "food" do
926
+ # match "bacon", action: :bacon, via: :get
927
+ # end
932
928
  def controller(controller)
933
929
  @scope = @scope.new(controller: controller)
934
930
  yield
@@ -938,42 +934,42 @@ module ActionDispatch
938
934
 
939
935
  # Scopes routes to a specific namespace. For example:
940
936
  #
941
- # namespace :admin do
942
- # resources :posts
943
- # end
937
+ # namespace :admin do
938
+ # resources :posts
939
+ # end
944
940
  #
945
941
  # This generates the following routes:
946
942
  #
947
- # admin_posts GET /admin/posts(.:format) admin/posts#index
948
- # admin_posts POST /admin/posts(.:format) admin/posts#create
949
- # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
950
- # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
951
- # admin_post GET /admin/posts/:id(.:format) admin/posts#show
952
- # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
953
- # 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
954
950
  #
955
- # === Options
951
+ # ### Options
956
952
  #
957
- # The +:path+, +:as+, +:module+, +:shallow_path+, and +:shallow_prefix+
958
- # 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.
959
955
  #
960
- # For options, see <tt>Base#match</tt>. For +:shallow_path+ option, see
961
- # <tt>Resources#resources</tt>.
956
+ # For options, see `Base#match`. For `:shallow_path` option, see
957
+ # `Resources#resources`.
962
958
  #
963
- # # accessible through /sekret/posts rather than /admin/posts
964
- # namespace :admin, path: "sekret" do
965
- # resources :posts
966
- # end
959
+ # # accessible through /sekret/posts rather than /admin/posts
960
+ # namespace :admin, path: "sekret" do
961
+ # resources :posts
962
+ # end
967
963
  #
968
- # # maps to +Sekret::PostsController+ rather than +Admin::PostsController+
969
- # namespace :admin, module: "sekret" do
970
- # resources :posts
971
- # end
964
+ # # maps to +Sekret::PostsController+ rather than +Admin::PostsController+
965
+ # namespace :admin, module: "sekret" do
966
+ # resources :posts
967
+ # end
972
968
  #
973
- # # generates +sekret_posts_path+ rather than +admin_posts_path+
974
- # namespace :admin, as: "sekret" do
975
- # resources :posts
976
- # end
969
+ # # generates +sekret_posts_path+ rather than +admin_posts_path+
970
+ # namespace :admin, as: "sekret" do
971
+ # resources :posts
972
+ # end
977
973
  def namespace(path, options = {}, &block)
978
974
  path = path.to_s
979
975
 
@@ -989,70 +985,74 @@ module ActionDispatch
989
985
  end
990
986
  end
991
987
 
992
- # === Parameter Restriction
993
- # Allows you to constrain the nested routes based on a set of rules.
994
- # 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:
995
992
  #
996
- # constraints(id: /\d+\.\d+/) do
997
- # resources :posts
998
- # end
993
+ # constraints(id: /\d+\.\d+/) do
994
+ # resources :posts
995
+ # end
999
996
  #
1000
- # Now routes such as +/posts/1+ will no longer be valid, but +/posts/1.1+ will be.
1001
- # 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.
1002
999
  #
1003
1000
  # You may use this to also restrict other parameters:
1004
1001
  #
1005
- # resources :posts do
1006
- # constraints(post_id: /\d+\.\d+/) do
1007
- # resources :comments
1002
+ # resources :posts do
1003
+ # constraints(post_id: /\d+\.\d+/) do
1004
+ # resources :comments
1005
+ # end
1008
1006
  # end
1009
- # end
1010
1007
  #
1011
- # === Restricting based on IP
1008
+ # ### Restricting based on IP
1012
1009
  #
1013
1010
  # Routes can also be constrained to an IP or a certain range of IP addresses:
1014
1011
  #
1015
- # constraints(ip: /192\.168\.\d+\.\d+/) do
1016
- # resources :posts
1017
- # end
1012
+ # constraints(ip: /192\.168\.\d+\.\d+/) do
1013
+ # resources :posts
1014
+ # end
1018
1015
  #
1019
- # Any user connecting from the 192.168.* range will be able to see this resource,
1020
- # 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.
1021
1019
  #
1022
- # === Dynamic request matching
1020
+ # ### Dynamic request matching
1023
1021
  #
1024
1022
  # Requests to routes can be constrained based on specific criteria:
1025
1023
  #
1026
- # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
1027
- # resources :iphones
1028
- # end
1024
+ # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
1025
+ # resources :iphones
1026
+ # end
1029
1027
  #
1030
- # You are able to move this logic out into a class if it is too complex for routes.
1031
- # This class must have a +matches?+ method defined on it which either returns +true+
1032
- # 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.
1033
1032
  #
1034
- # class Iphone
1035
- # def self.matches?(request)
1036
- # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
1037
- # end
1038
- # end
1033
+ # class Iphone
1034
+ # def self.matches?(request)
1035
+ # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
1036
+ # end
1037
+ # end
1039
1038
  #
1040
- # An expected place for this code would be +lib/constraints+.
1039
+ # An expected place for this code would be `lib/constraints`.
1041
1040
  #
1042
1041
  # This class is then used like this:
1043
1042
  #
1044
- # constraints(Iphone) do
1045
- # resources :iphones
1046
- # end
1043
+ # constraints(Iphone) do
1044
+ # resources :iphones
1045
+ # end
1047
1046
  def constraints(constraints = {}, &block)
1048
1047
  scope(constraints: constraints, &block)
1049
1048
  end
1050
1049
 
1051
1050
  # Allows you to set default parameters for a route, such as this:
1052
- # defaults id: 'home' do
1053
- # match 'scoped_pages/(:id)', to: 'pages#show'
1054
- # end
1055
- # 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'.
1056
1056
  def defaults(defaults = {})
1057
1057
  @scope = @scope.new(defaults: merge_defaults_scope(@scope[:defaults], defaults))
1058
1058
  yield
@@ -1128,48 +1128,46 @@ module ActionDispatch
1128
1128
  end
1129
1129
  end
1130
1130
 
1131
- # Resource routing allows you to quickly declare all of the common routes
1132
- # for a given resourceful controller. Instead of declaring separate routes
1133
- # for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
1134
- # 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:
1135
1135
  #
1136
- # resources :photos
1136
+ # resources :photos
1137
1137
  #
1138
- # Sometimes, you have a resource that clients always look up without
1139
- # referencing an ID. A common example, /profile always shows the profile of
1140
- # the currently logged in user. In this case, you can use a singular resource
1141
- # 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.
1142
1142
  #
1143
- # resource :profile
1143
+ # resource :profile
1144
1144
  #
1145
- # It's common to have resources that are logically children of other
1146
- # resources:
1145
+ # It's common to have resources that are logically children of other resources:
1147
1146
  #
1148
- # resources :magazines do
1149
- # resources :ads
1150
- # end
1147
+ # resources :magazines do
1148
+ # resources :ads
1149
+ # end
1151
1150
  #
1152
1151
  # You may wish to organize groups of controllers under a namespace. Most
1153
- # commonly, you might group a number of administrative controllers under
1154
- # an +admin+ namespace. You would place these controllers under the
1155
- # <tt>app/controllers/admin</tt> directory, and you can group them together
1156
- # in your router:
1157
- #
1158
- # namespace "admin" do
1159
- # resources :posts, :comments
1160
- # 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:
1161
1156
  #
1162
- # By default the +:id+ parameter doesn't accept dots. If you need to
1163
- # use dots as part of the +:id+ parameter add a constraint which
1164
- # overrides this restriction, e.g:
1157
+ # namespace "admin" do
1158
+ # resources :posts, :comments
1159
+ # end
1165
1160
  #
1166
- # 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:
1167
1164
  #
1168
- # This allows any character other than a slash as part of your +:id+.
1165
+ # resources :articles, id: /[^\/]+/
1169
1166
  #
1167
+ # This allows any character other than a slash as part of your `:id`.
1170
1168
  module Resources
1171
- # CANONICAL_ACTIONS holds all actions that does not need a prefix or
1172
- # 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.
1173
1171
  VALID_ON_OPTIONS = [:new, :collection, :member]
1174
1172
  RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except, :param, :concerns]
1175
1173
  CANONICAL_ACTIONS = %w(index create new show update destroy)
@@ -1232,8 +1230,8 @@ module ActionDispatch
1232
1230
 
1233
1231
  alias :member_name :singular
1234
1232
 
1235
- # Checks for uncountable plurals, and appends "_index" if the plural
1236
- # and singular form are the same.
1233
+ # Checks for uncountable plurals, and appends "_index" if the plural and
1234
+ # singular form are the same.
1237
1235
  def collection_name
1238
1236
  singular == plural ? "#{plural}_index" : plural
1239
1237
  end
@@ -1306,37 +1304,35 @@ module ActionDispatch
1306
1304
  @scope[:path_names].merge!(options)
1307
1305
  end
1308
1306
 
1309
- # Sometimes, you have a resource that clients always look up without
1310
- # referencing an ID. A common example, /profile always shows the
1311
- # profile of the currently logged in user. In this case, you can use
1312
- # a singular resource to map /profile (rather than /profile/:id) to
1313
- # 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:
1314
1311
  #
1315
- # resource :profile
1312
+ # resource :profile
1316
1313
  #
1317
- # This creates six different routes in your application, all mapping to
1318
- # the +Profiles+ controller (note that the controller is named after
1319
- # 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):
1320
1316
  #
1321
- # GET /profile/new
1322
- # GET /profile
1323
- # GET /profile/edit
1324
- # PATCH/PUT /profile
1325
- # DELETE /profile
1326
- # POST /profile
1317
+ # GET /profile/new
1318
+ # GET /profile
1319
+ # GET /profile/edit
1320
+ # PATCH/PUT /profile
1321
+ # DELETE /profile
1322
+ # POST /profile
1327
1323
  #
1328
- # If you want instances of a model to work with this resource via
1329
- # record identification (e.g. in +form_with+ or +redirect_to+), you
1330
- # 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):
1331
1327
  #
1332
- # resource :profile
1333
- # resolve('Profile') { [:profile] }
1328
+ # resource :profile
1329
+ # resolve('Profile') { [:profile] }
1334
1330
  #
1335
- # # Enables this to work with singular routes:
1336
- # form_with(model: @profile) {}
1331
+ # # Enables this to work with singular routes:
1332
+ # form_with(model: @profile) {}
1337
1333
  #
1338
- # === Options
1339
- # Takes same options as resources[rdoc-ref:#resources]
1334
+ # ### Options
1335
+ # Takes same options as [resources](rdoc-ref:#resources)
1340
1336
  def resource(*resources, &block)
1341
1337
  options = resources.extract_options!.dup
1342
1338
 
@@ -1366,143 +1362,147 @@ module ActionDispatch
1366
1362
  self
1367
1363
  end
1368
1364
 
1369
- # In \Rails, a resourceful route provides a mapping between HTTP verbs
1370
- # and URLs and controller actions. By convention, each action also maps
1371
- # to particular CRUD operations in a database. A single entry in the
1372
- # 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
1373
1368
  #
1374
- # resources :photos
1369
+ # resources :photos
1375
1370
  #
1376
- # creates seven different routes in your application, all mapping to
1377
- # the +Photos+ controller:
1371
+ # creates seven different routes in your application, all mapping to the
1372
+ # `Photos` controller:
1378
1373
  #
1379
- # GET /photos
1380
- # GET /photos/new
1381
- # POST /photos
1382
- # GET /photos/:id
1383
- # GET /photos/:id/edit
1384
- # PATCH/PUT /photos/:id
1385
- # 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
1386
1381
  #
1387
1382
  # Resources can also be nested infinitely by using this block syntax:
1388
1383
  #
1389
- # resources :photos do
1390
- # resources :comments
1391
- # end
1384
+ # resources :photos do
1385
+ # resources :comments
1386
+ # end
1392
1387
  #
1393
1388
  # This generates the following comments routes:
1394
1389
  #
1395
- # GET /photos/:photo_id/comments
1396
- # GET /photos/:photo_id/comments/new
1397
- # POST /photos/:photo_id/comments
1398
- # GET /photos/:photo_id/comments/:id
1399
- # GET /photos/:photo_id/comments/:id/edit
1400
- # PATCH/PUT /photos/:photo_id/comments/:id
1401
- # 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
1402
1397
  #
1403
- # === Options
1404
- # 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:
1405
1400
  #
1406
- # [:path_names]
1407
- # Allows you to change the segment component of the +edit+ and +new+ actions.
1408
- # 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.
1409
1404
  #
1410
- # resources :posts, path_names: { new: "brand_new" }
1405
+ # resources :posts, path_names: { new: "brand_new" }
1411
1406
  #
1412
- # 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.
1413
1408
  #
1414
- # [:path]
1415
- # Allows you to change the path prefix for the resource.
1409
+ # :path
1410
+ # : Allows you to change the path prefix for the resource.
1416
1411
  #
1417
- # resources :posts, path: 'postings'
1412
+ # resources :posts, path: 'postings'
1418
1413
  #
1419
- # 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.
1420
1416
  #
1421
- # [:only]
1422
- # Only generate routes for the given actions.
1417
+ # :only
1418
+ # : Only generate routes for the given actions.
1423
1419
  #
1424
- # resources :cows, only: :show
1425
- # resources :cows, only: [:show, :index]
1420
+ # resources :cows, only: :show
1421
+ # resources :cows, only: [:show, :index]
1426
1422
  #
1427
- # [:except]
1428
- # Generate all routes except for the given actions.
1423
+ # :except
1424
+ # : Generate all routes except for the given actions.
1429
1425
  #
1430
- # resources :cows, except: :show
1431
- # resources :cows, except: [:show, :index]
1426
+ # resources :cows, except: :show
1427
+ # resources :cows, except: [:show, :index]
1432
1428
  #
1433
- # [:shallow]
1434
- # Generates shallow routes for nested resource(s). When placed on a parent resource,
1435
- # 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.
1436
1432
  #
1437
- # resources :posts, shallow: true do
1438
- # resources :comments
1439
- # end
1433
+ # resources :posts, shallow: true do
1434
+ # resources :comments
1435
+ # end
1440
1436
  #
1441
- # Is the same as:
1437
+ # Is the same as:
1442
1438
  #
1443
- # resources :posts do
1444
- # resources :comments, except: [:show, :edit, :update, :destroy]
1445
- # end
1446
- # 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]
1447
1443
  #
1448
- # This allows URLs for resources that otherwise would be deeply nested such
1449
- # as a comment on a blog post like <tt>/posts/a-long-permalink/comments/1234</tt>
1450
- # 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`.
1451
1447
  #
1452
- # 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.
1453
1450
  #
1454
- # [:shallow_path]
1455
- # Prefixes nested shallow routes with the specified path.
1451
+ # :shallow_path
1452
+ # : Prefixes nested shallow routes with the specified path.
1456
1453
  #
1457
- # scope shallow_path: "sekret" do
1458
- # resources :posts do
1459
- # resources :comments, shallow: true
1460
- # end
1461
- # end
1454
+ # scope shallow_path: "sekret" do
1455
+ # resources :posts do
1456
+ # resources :comments, shallow: true
1457
+ # end
1458
+ # end
1462
1459
  #
1463
- # 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:
1464
1462
  #
1465
- # post_comments GET /posts/:post_id/comments(.:format)
1466
- # post_comments POST /posts/:post_id/comments(.:format)
1467
- # new_post_comment GET /posts/:post_id/comments/new(.:format)
1468
- # edit_comment GET /sekret/comments/:id/edit(.:format)
1469
- # comment GET /sekret/comments/:id(.:format)
1470
- # comment PATCH/PUT /sekret/comments/:id(.:format)
1471
- # 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)
1472
1470
  #
1473
- # [:shallow_prefix]
1474
- # Prefixes nested shallow route names with specified prefix.
1471
+ # :shallow_prefix
1472
+ # : Prefixes nested shallow route names with specified prefix.
1475
1473
  #
1476
- # scope shallow_prefix: "sekret" do
1477
- # resources :posts do
1478
- # resources :comments, shallow: true
1479
- # end
1480
- # end
1474
+ # scope shallow_prefix: "sekret" do
1475
+ # resources :posts do
1476
+ # resources :comments, shallow: true
1477
+ # end
1478
+ # end
1481
1479
  #
1482
- # The +comments+ resource here will have the following routes generated for it:
1480
+ # The `comments` resource here will have the following routes generated for
1481
+ # it:
1483
1482
  #
1484
- # post_comments GET /posts/:post_id/comments(.:format)
1485
- # post_comments POST /posts/:post_id/comments(.:format)
1486
- # new_post_comment GET /posts/:post_id/comments/new(.:format)
1487
- # edit_sekret_comment GET /comments/:id/edit(.:format)
1488
- # sekret_comment GET /comments/:id(.:format)
1489
- # sekret_comment PATCH/PUT /comments/:id(.:format)
1490
- # sekret_comment DELETE /comments/:id(.:format)
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)
1491
1490
  #
1492
- # [:format]
1493
- # Allows you to specify the default value for optional +format+
1494
- # segment or disable it by supplying +false+.
1491
+ # :format
1492
+ # : Allows you to specify the default value for optional `format` segment or
1493
+ # disable it by supplying `false`.
1495
1494
  #
1496
- # [:param]
1497
- # Allows you to override the default param name of +:id+ in the URL.
1495
+ # :param
1496
+ # : Allows you to override the default param name of `:id` in the URL.
1498
1497
  #
1499
- # === Examples
1500
1498
  #
1501
- # # routes call +Admin::PostsController+
1502
- # resources :posts, module: "admin"
1499
+ # ### Examples
1503
1500
  #
1504
- # # resource actions are at /admin/posts.
1505
- # resources :posts, path: "admin/posts"
1501
+ # # routes call +Admin::PostsController+
1502
+ # resources :posts, module: "admin"
1503
+ #
1504
+ # # resource actions are at /admin/posts.
1505
+ # resources :posts, path: "admin/posts"
1506
1506
  def resources(*resources, &block)
1507
1507
  options = resources.extract_options!.dup
1508
1508
 
@@ -1535,16 +1535,15 @@ module ActionDispatch
1535
1535
 
1536
1536
  # To add a route to the collection:
1537
1537
  #
1538
- # resources :photos do
1539
- # collection do
1540
- # get 'search'
1538
+ # resources :photos do
1539
+ # collection do
1540
+ # get 'search'
1541
+ # end
1541
1542
  # end
1542
- # end
1543
1543
  #
1544
- # This will enable \Rails to recognize paths such as <tt>/photos/search</tt>
1545
- # with GET, and route to the search action of +PhotosController+. It will also
1546
- # create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
1547
- # 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.
1548
1547
  def collection(&block)
1549
1548
  unless resource_scope?
1550
1549
  raise ArgumentError, "can't use collection outside resource(s) scope"
@@ -1557,15 +1556,15 @@ module ActionDispatch
1557
1556
 
1558
1557
  # To add a member route, add a member block into the resource block:
1559
1558
  #
1560
- # resources :photos do
1561
- # member do
1562
- # get 'preview'
1559
+ # resources :photos do
1560
+ # member do
1561
+ # get 'preview'
1562
+ # end
1563
1563
  # end
1564
- # end
1565
1564
  #
1566
- # This will recognize <tt>/photos/1/preview</tt> with GET, and route to the
1567
- # preview action of +PhotosController+. It will also create the
1568
- # <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.
1569
1568
  def member(&block)
1570
1569
  unless resource_scope?
1571
1570
  raise ArgumentError, "can't use member outside resource(s) scope"
@@ -1632,29 +1631,28 @@ module ActionDispatch
1632
1631
  !parent_resource.singleton? && @scope[:shallow]
1633
1632
  end
1634
1633
 
1635
- # Loads another routes file with the given +name+ located inside the
1636
- # +config/routes+ directory. In that file, you can use the normal
1637
- # routing DSL, but <i>do not</i> surround it with a
1638
- # +Rails.application.routes.draw+ block.
1639
- #
1640
- # # config/routes.rb
1641
- # Rails.application.routes.draw do
1642
- # draw :admin # Loads `config/routes/admin.rb`
1643
- # draw "third_party/some_gem" # Loads `config/routes/third_party/some_gem.rb`
1644
- # end
1645
- #
1646
- # # config/routes/admin.rb
1647
- # namespace :admin do
1648
- # resources :accounts
1649
- # end
1650
- #
1651
- # # config/routes/third_party/some_gem.rb
1652
- # mount SomeGem::Engine, at: "/some_gem"
1653
- #
1654
- # <b>CAUTION:</b> Use this feature with care. Having multiple routes
1655
- # files can negatively impact discoverability and readability. For most
1656
- # applications — even those with a few hundred routes — it's easier for
1657
- # 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.
1658
1656
  def draw(name)
1659
1657
  path = @draw_paths.find do |_path|
1660
1658
  File.exist? "#{_path}/#{name}.rb"
@@ -1671,12 +1669,12 @@ module ActionDispatch
1671
1669
  instance_eval(File.read(route_path), route_path.to_s)
1672
1670
  end
1673
1671
 
1674
- # Matches a URL pattern to one or more routes.
1675
- # 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).
1676
1674
  #
1677
- # match 'path' => 'controller#action', via: :patch
1678
- # match 'path', to: 'controller#action', via: :post
1679
- # 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
1680
1678
  def match(path, *rest, &block)
1681
1679
  if rest.empty? && Hash === path
1682
1680
  options = path
@@ -1711,19 +1709,19 @@ module ActionDispatch
1711
1709
  end
1712
1710
  end
1713
1711
 
1714
- # 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:
1715
1713
  #
1716
- # root to: 'pages#main'
1714
+ # root to: 'pages#main'
1717
1715
  #
1718
- # For options, see +match+, as +root+ uses it internally.
1716
+ # For options, see `match`, as `root` uses it internally.
1719
1717
  #
1720
1718
  # You can also pass a string which will expand
1721
1719
  #
1722
- # root 'pages#main'
1720
+ # root 'pages#main'
1723
1721
  #
1724
- # You should put the root route at the top of <tt>config/routes.rb</tt>,
1725
- # because this means it will be matched first. As this is the most popular route
1726
- # 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.
1727
1725
  def root(path, options = {})
1728
1726
  if path.is_a?(String)
1729
1727
  options[:to] = path
@@ -1901,9 +1899,9 @@ module ActionDispatch
1901
1899
  candidate = action_name.select(&:present?).join("_")
1902
1900
 
1903
1901
  unless candidate.empty?
1904
- # If a name was not explicitly given, we check if it is valid
1905
- # and return nil in case it isn't. Otherwise, we pass the invalid name
1906
- # 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.
1907
1905
  if as.nil?
1908
1906
  candidate unless !candidate.match?(/\A[_a-z]/i) || has_named_route?(candidate)
1909
1907
  else
@@ -2026,7 +2024,7 @@ module ActionDispatch
2026
2024
  name_for_action(options.delete(:as), action)
2027
2025
  end
2028
2026
 
2029
- path = Mapping.normalize_path RFC2396_PARSER.escape(path), formatted
2027
+ path = Mapping.normalize_path URI::DEFAULT_PARSER.escape(path), formatted
2030
2028
  ast = Journey::Parser.parse path
2031
2029
 
2032
2030
  mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
@@ -2039,83 +2037,81 @@ module ActionDispatch
2039
2037
  end
2040
2038
  end
2041
2039
 
2042
- # Routing Concerns allow you to declare common routes that can be reused
2043
- # inside others resources and routes.
2040
+ # Routing Concerns allow you to declare common routes that can be reused inside
2041
+ # others resources and routes.
2044
2042
  #
2045
- # concern :commentable do
2046
- # resources :comments
2047
- # end
2043
+ # concern :commentable do
2044
+ # resources :comments
2045
+ # end
2048
2046
  #
2049
- # concern :image_attachable do
2050
- # resources :images, only: :index
2051
- # end
2047
+ # concern :image_attachable do
2048
+ # resources :images, only: :index
2049
+ # end
2052
2050
  #
2053
2051
  # These concerns are used in Resources routing:
2054
2052
  #
2055
- # resources :messages, concerns: [:commentable, :image_attachable]
2053
+ # resources :messages, concerns: [:commentable, :image_attachable]
2056
2054
  #
2057
2055
  # or in a scope or namespace:
2058
2056
  #
2059
- # namespace :posts do
2060
- # concerns :commentable
2061
- # end
2057
+ # namespace :posts do
2058
+ # concerns :commentable
2059
+ # end
2062
2060
  module Concerns
2063
2061
  # Define a routing concern using a name.
2064
2062
  #
2065
- # Concerns may be defined inline, using a block, or handled by
2066
- # 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.
2067
2065
  #
2068
- # The concern object, if supplied, should respond to <tt>call</tt>,
2069
- # which will receive two parameters:
2066
+ # The concern object, if supplied, should respond to `call`, which will receive
2067
+ # two parameters:
2070
2068
  #
2071
- # * The current mapper
2072
- # * 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
2073
2071
  #
2074
- # Options may also be used by concerns defined in a block by accepting
2075
- # a block parameter. So, using a block, you might do something as
2076
- # simple as limit the actions available on certain resources, passing
2077
- # 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:
2078
2076
  #
2079
- # concern :commentable do |options|
2080
- # resources :comments, options
2081
- # end
2077
+ # concern :commentable do |options|
2078
+ # resources :comments, options
2079
+ # end
2082
2080
  #
2083
- # resources :posts, concerns: :commentable
2084
- # resources :archived_posts do
2085
- # # Don't allow comments on archived posts
2086
- # concerns :commentable, only: [:index, :show]
2087
- # 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
2088
2086
  #
2089
- # Or, using a callable object, you might implement something more
2090
- # specific to your application, which would be out of place in your
2091
- # 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.
2092
2089
  #
2093
- # # purchasable.rb
2094
- # class Purchasable
2095
- # def initialize(defaults = {})
2096
- # @defaults = defaults
2097
- # end
2090
+ # # purchasable.rb
2091
+ # class Purchasable
2092
+ # def initialize(defaults = {})
2093
+ # @defaults = defaults
2094
+ # end
2098
2095
  #
2099
- # def call(mapper, options = {})
2100
- # options = @defaults.merge(options)
2101
- # mapper.resources :purchases
2102
- # mapper.resources :receipts
2103
- # 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
2104
2102
  # end
2105
- # end
2106
2103
  #
2107
- # # routes.rb
2108
- # concern :purchasable, Purchasable.new(returnable: true)
2104
+ # # routes.rb
2105
+ # concern :purchasable, Purchasable.new(returnable: true)
2109
2106
  #
2110
- # resources :toys, concerns: :purchasable
2111
- # resources :electronics, concerns: :purchasable
2112
- # resources :pets do
2113
- # concerns :purchasable, returnable: false
2114
- # end
2107
+ # resources :toys, concerns: :purchasable
2108
+ # resources :electronics, concerns: :purchasable
2109
+ # resources :pets do
2110
+ # concerns :purchasable, returnable: false
2111
+ # end
2115
2112
  #
2116
- # Any routing helpers can be used inside a concern. If using a
2117
- # callable, they're accessible from the Mapper that's passed to
2118
- # <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`.
2119
2115
  def concern(name, callable = nil, &block)
2120
2116
  callable ||= lambda { |mapper, options| mapper.instance_exec(options, &block) }
2121
2117
  @concerns[name] = callable
@@ -2123,15 +2119,15 @@ module ActionDispatch
2123
2119
 
2124
2120
  # Use the named concerns
2125
2121
  #
2126
- # resources :posts do
2127
- # concerns :commentable
2128
- # end
2122
+ # resources :posts do
2123
+ # concerns :commentable
2124
+ # end
2129
2125
  #
2130
2126
  # Concerns also work in any routes helper that you want to use:
2131
2127
  #
2132
- # namespace :posts do
2133
- # concerns :commentable
2134
- # end
2128
+ # namespace :posts do
2129
+ # concerns :commentable
2130
+ # end
2135
2131
  def concerns(*args)
2136
2132
  options = args.extract_options!
2137
2133
  args.flatten.each do |name|
@@ -2145,53 +2141,55 @@ module ActionDispatch
2145
2141
  end
2146
2142
 
2147
2143
  module CustomUrls
2148
- # Define custom URL helpers that will be added to the application's
2149
- # routes. This allows you to override and/or replace the default behavior
2150
- # 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:
2151
2147
  #
2152
- # direct :homepage do
2153
- # "https://rubyonrails.org"
2154
- # end
2148
+ # direct :homepage do
2149
+ # "https://rubyonrails.org"
2150
+ # end
2155
2151
  #
2156
- # direct :commentable do |model|
2157
- # [ model, anchor: model.dom_id ]
2158
- # end
2152
+ # direct :commentable do |model|
2153
+ # [ model, anchor: model.dom_id ]
2154
+ # end
2155
+ #
2156
+ # direct :main do
2157
+ # { controller: "pages", action: "index", subdomain: "www" }
2158
+ # end
2159
2159
  #
2160
- # direct :main do
2161
- # { controller: "pages", action: "index", subdomain: "www" }
2162
- # end
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:
2163
2163
  #
2164
- # The return value from the block passed to +direct+ must be a valid set of
2165
- # arguments for +url_for+ which will actually build the URL string. This can
2166
- # be one of the following:
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
2167
2169
  #
2168
- # * A string, which is treated as a generated URL
2169
- # * A hash, e.g. <tt>{ controller: "pages", action: "index" }</tt>
2170
- # * An array, which is passed to +polymorphic_url+
2171
- # * An Active Model instance
2172
- # * An Active Model class
2173
2170
  #
2174
- # NOTE: Other URL helpers can be called in the block but be careful not to invoke
2175
- # your custom URL helper again otherwise it will result in a stack overflow error.
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.
2176
2174
  #
2177
- # You can also specify default options that will be passed through to
2178
- # your URL helper definition, e.g:
2175
+ # You can also specify default options that will be passed through to your URL
2176
+ # helper definition, e.g:
2179
2177
  #
2180
- # direct :browse, page: 1, size: 10 do |options|
2181
- # [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
2182
- # end
2178
+ # direct :browse, page: 1, size: 10 do |options|
2179
+ # [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
2180
+ # end
2183
2181
  #
2184
- # In this instance the +params+ object comes from the context in which the
2185
- # block is executed, e.g. generating a URL inside a controller action or a view.
2186
- # If the block is executed where there isn't a +params+ object such as this:
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:
2187
2185
  #
2188
- # Rails.application.routes.url_helpers.browse_path
2186
+ # Rails.application.routes.url_helpers.browse_path
2189
2187
  #
2190
- # then it will raise a +NameError+. Because of this you need to be aware of the
2188
+ # then it will raise a `NameError`. Because of this you need to be aware of the
2191
2189
  # context in which you will use your custom URL helper when defining it.
2192
2190
  #
2193
- # NOTE: The +direct+ method can't be used inside of a scope block such as
2194
- # +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.
2195
2193
  def direct(name, options = {}, &block)
2196
2194
  unless @scope.root?
2197
2195
  raise RuntimeError, "The direct method can't be used inside a routes scope block"
@@ -2200,50 +2198,50 @@ module ActionDispatch
2200
2198
  @set.add_url_helper(name, options, &block)
2201
2199
  end
2202
2200
 
2203
- # Define custom polymorphic mappings of models to URLs. This alters the
2204
- # behavior of +polymorphic_url+ and consequently the behavior of
2205
- # +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:
2206
2204
  #
2207
- # resource :basket
2205
+ # resource :basket
2208
2206
  #
2209
- # resolve "Basket" do
2210
- # [:basket]
2211
- # end
2207
+ # resolve "Basket" do
2208
+ # [:basket]
2209
+ # end
2212
2210
  #
2213
- # This will now generate "/basket" when a +Basket+ instance is passed to
2214
- # +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".
2215
2213
  #
2216
- # NOTE: This custom behavior only applies to simple polymorphic URLs where
2217
- # 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:
2218
2216
  #
2219
- # # config/routes.rb
2220
- # resource :profile
2221
- # namespace :admin do
2222
- # resources :users
2223
- # end
2217
+ # # config/routes.rb
2218
+ # resource :profile
2219
+ # namespace :admin do
2220
+ # resources :users
2221
+ # end
2224
2222
  #
2225
- # resolve("User") { [:profile] }
2223
+ # resolve("User") { [:profile] }
2226
2224
  #
2227
- # # app/views/application/_menu.html.erb
2228
- # link_to "Profile", @current_user
2229
- # 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]
2230
2228
  #
2231
- # The first +link_to+ will generate "/profile" but the second will generate
2232
- # 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".
2233
2231
  #
2234
- # You can pass options to a polymorphic mapping - the arity for the block
2235
- # 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:
2236
2234
  #
2237
- # resolve "Basket", anchor: "items" do |basket, options|
2238
- # [:basket, options]
2239
- # end
2235
+ # resolve "Basket", anchor: "items" do |basket, options|
2236
+ # [:basket, options]
2237
+ # end
2240
2238
  #
2241
- # This generates the URL "/basket#items" because when the last item in an
2242
- # array passed to +polymorphic_url+ is a hash then it's treated as options
2243
- # 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.
2244
2242
  #
2245
- # NOTE: The +resolve+ method can't be used inside of a scope block such as
2246
- # +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.
2247
2245
  def resolve(*args, &block)
2248
2246
  unless @scope.root?
2249
2247
  raise RuntimeError, "The resolve method can't be used inside a routes scope block"