actionpack 8.0.2 → 8.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +252 -137
  3. data/README.rdoc +1 -1
  4. data/lib/abstract_controller/asset_paths.rb +4 -2
  5. data/lib/abstract_controller/base.rb +11 -14
  6. data/lib/abstract_controller/caching.rb +6 -3
  7. data/lib/abstract_controller/collector.rb +1 -1
  8. data/lib/abstract_controller/logger.rb +2 -1
  9. data/lib/action_controller/base.rb +1 -1
  10. data/lib/action_controller/caching.rb +1 -2
  11. data/lib/action_controller/form_builder.rb +1 -1
  12. data/lib/action_controller/log_subscriber.rb +7 -0
  13. data/lib/action_controller/metal/allow_browser.rb +1 -1
  14. data/lib/action_controller/metal/conditional_get.rb +25 -0
  15. data/lib/action_controller/metal/data_streaming.rb +1 -3
  16. data/lib/action_controller/metal/exceptions.rb +5 -0
  17. data/lib/action_controller/metal/flash.rb +1 -4
  18. data/lib/action_controller/metal/head.rb +3 -1
  19. data/lib/action_controller/metal/live.rb +0 -6
  20. data/lib/action_controller/metal/permissions_policy.rb +9 -0
  21. data/lib/action_controller/metal/rate_limiting.rb +22 -7
  22. data/lib/action_controller/metal/redirecting.rb +63 -7
  23. data/lib/action_controller/metal/renderers.rb +27 -6
  24. data/lib/action_controller/metal/rendering.rb +8 -2
  25. data/lib/action_controller/metal/request_forgery_protection.rb +18 -10
  26. data/lib/action_controller/metal/rescue.rb +9 -0
  27. data/lib/action_controller/railtie.rb +2 -6
  28. data/lib/action_controller/renderer.rb +0 -1
  29. data/lib/action_dispatch/constants.rb +6 -0
  30. data/lib/action_dispatch/http/cache.rb +111 -1
  31. data/lib/action_dispatch/http/content_security_policy.rb +13 -1
  32. data/lib/action_dispatch/http/filter_parameters.rb +5 -3
  33. data/lib/action_dispatch/http/mime_negotiation.rb +8 -3
  34. data/lib/action_dispatch/http/mime_types.rb +1 -0
  35. data/lib/action_dispatch/http/param_builder.rb +28 -27
  36. data/lib/action_dispatch/http/parameters.rb +3 -3
  37. data/lib/action_dispatch/http/permissions_policy.rb +4 -0
  38. data/lib/action_dispatch/http/query_parser.rb +12 -10
  39. data/lib/action_dispatch/http/request.rb +10 -5
  40. data/lib/action_dispatch/http/response.rb +65 -17
  41. data/lib/action_dispatch/http/url.rb +101 -5
  42. data/lib/action_dispatch/journey/gtg/simulator.rb +33 -12
  43. data/lib/action_dispatch/journey/gtg/transition_table.rb +29 -39
  44. data/lib/action_dispatch/journey/nodes/node.rb +2 -1
  45. data/lib/action_dispatch/journey/route.rb +45 -31
  46. data/lib/action_dispatch/journey/router/utils.rb +8 -14
  47. data/lib/action_dispatch/journey/router.rb +59 -81
  48. data/lib/action_dispatch/journey/routes.rb +7 -0
  49. data/lib/action_dispatch/journey/visitors.rb +55 -23
  50. data/lib/action_dispatch/journey/visualizer/fsm.js +4 -6
  51. data/lib/action_dispatch/middleware/cookies.rb +4 -2
  52. data/lib/action_dispatch/middleware/debug_exceptions.rb +10 -2
  53. data/lib/action_dispatch/middleware/debug_view.rb +11 -0
  54. data/lib/action_dispatch/middleware/exception_wrapper.rb +14 -8
  55. data/lib/action_dispatch/middleware/executor.rb +12 -2
  56. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -6
  57. data/lib/action_dispatch/middleware/session/cache_store.rb +17 -0
  58. data/lib/action_dispatch/middleware/templates/rescues/_copy_button.html.erb +1 -0
  59. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +3 -2
  60. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +9 -5
  61. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
  62. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +1 -0
  63. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +1 -0
  64. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +50 -0
  65. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -0
  66. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -0
  67. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -0
  68. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -0
  69. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -0
  70. data/lib/action_dispatch/railtie.rb +10 -2
  71. data/lib/action_dispatch/routing/inspector.rb +4 -1
  72. data/lib/action_dispatch/routing/mapper.rb +323 -173
  73. data/lib/action_dispatch/routing/route_set.rb +3 -6
  74. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +2 -2
  75. data/lib/action_dispatch/testing/assertion_response.rb +1 -1
  76. data/lib/action_dispatch/testing/assertions/response.rb +14 -0
  77. data/lib/action_dispatch/testing/assertions/routing.rb +11 -3
  78. data/lib/action_pack/gem_version.rb +3 -3
  79. metadata +13 -12
@@ -87,7 +87,7 @@ module ActionDispatch
87
87
  attr_reader :path, :requirements, :defaults, :to, :default_controller,
88
88
  :default_action, :required_defaults, :ast, :scope_options
89
89
 
90
- def self.build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
90
+ def self.build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, internal, options)
91
91
  scope_params = {
92
92
  blocks: scope[:blocks] || [],
93
93
  constraints: scope[:constraints] || {},
@@ -98,7 +98,7 @@ module ActionDispatch
98
98
 
99
99
  new set: set, ast: ast, controller: controller, default_action: default_action,
100
100
  to: to, formatted: formatted, via: via, options_constraints: options_constraints,
101
- anchor: anchor, scope_params: scope_params, options: scope_params[:options].merge(options)
101
+ anchor: anchor, scope_params: scope_params, internal: internal, options: scope_params[:options].merge(options)
102
102
  end
103
103
 
104
104
  def self.check_via(via)
@@ -129,7 +129,7 @@ module ActionDispatch
129
129
  format != false && !path.match?(OPTIONAL_FORMAT_REGEX)
130
130
  end
131
131
 
132
- def initialize(set:, ast:, controller:, default_action:, to:, formatted:, via:, options_constraints:, anchor:, scope_params:, options:)
132
+ def initialize(set:, ast:, controller:, default_action:, to:, formatted:, via:, options_constraints:, anchor:, scope_params:, internal:, options:)
133
133
  @defaults = scope_params[:defaults]
134
134
  @set = set
135
135
  @to = intern(to)
@@ -137,7 +137,7 @@ module ActionDispatch
137
137
  @default_action = intern(default_action)
138
138
  @anchor = anchor
139
139
  @via = via
140
- @internal = options.delete(:internal)
140
+ @internal = internal
141
141
  @scope_options = scope_params[:options]
142
142
  ast = Journey::Ast.new(ast, formatted)
143
143
 
@@ -183,7 +183,7 @@ module ActionDispatch
183
183
  def make_route(name, precedence)
184
184
  Journey::Route.new(name: name, app: application, path: path, constraints: conditions,
185
185
  required_defaults: required_defaults, defaults: defaults,
186
- request_method_match: request_method, precedence: precedence,
186
+ via: @via, precedence: precedence,
187
187
  scope_options: scope_options, internal: @internal, source_location: route_source_location)
188
188
  end
189
189
 
@@ -204,11 +204,6 @@ module ActionDispatch
204
204
  end
205
205
  private :build_conditions
206
206
 
207
- def request_method
208
- @via.map { |x| Journey::Route.verb_matcher(x) }
209
- end
210
- private :request_method
211
-
212
207
  private
213
208
  def intern(object)
214
209
  object.is_a?(String) ? -object : object
@@ -607,17 +602,32 @@ module ActionDispatch
607
602
  #
608
603
  # This will generate the `exciting_path` and `exciting_url` helpers which can be
609
604
  # used to navigate to this mounted app.
610
- def mount(app, options = nil)
611
- if options
612
- path = options.delete(:at)
613
- elsif Hash === app
614
- options = app
615
- app, path = options.find { |k, _| k.respond_to?(:call) }
616
- options.delete(app) if app
605
+ def mount(app = nil, deprecated_options = nil, as: DEFAULT, via: nil, at: nil, defaults: nil, constraints: nil, anchor: false, format: false, path: nil, internal: nil, **mapping, &block)
606
+ if deprecated_options.is_a?(Hash)
607
+ as = assign_deprecated_option(deprecated_options, :as, :mount) if deprecated_options.key?(:as)
608
+ via ||= assign_deprecated_option(deprecated_options, :via, :mount)
609
+ at ||= assign_deprecated_option(deprecated_options, :at, :mount)
610
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :mount)
611
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :mount)
612
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :mount) if deprecated_options.key?(:anchor)
613
+ format = assign_deprecated_option(deprecated_options, :format, :mount) if deprecated_options.key?(:format)
614
+ path ||= assign_deprecated_option(deprecated_options, :path, :mount)
615
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :mount)
616
+ assign_deprecated_options(deprecated_options, mapping, :mount)
617
+ end
618
+
619
+ path_or_action = at
620
+
621
+ if app.nil?
622
+ hash_app, hash_path = mapping.find { |key, _| key.respond_to?(:call) }
623
+ mapping.delete(hash_app) if hash_app
624
+
625
+ app ||= hash_app
626
+ path_or_action ||= hash_path
617
627
  end
618
628
 
619
629
  raise ArgumentError, "A rack application must be specified" unless app.respond_to?(:call)
620
- raise ArgumentError, <<~MSG unless path
630
+ raise ArgumentError, <<~MSG unless path_or_action
621
631
  Must be called with mount point
622
632
 
623
633
  mount SomeRackApp, at: "some_route"
@@ -626,12 +636,12 @@ module ActionDispatch
626
636
  MSG
627
637
 
628
638
  rails_app = rails_app? app
629
- options[:as] ||= app_name(app, rails_app)
639
+ as = app_name(app, rails_app) if as == DEFAULT
630
640
 
631
- target_as = name_for_action(options[:as], path)
632
- options[:via] ||= :all
641
+ target_as = name_for_action(as, path_or_action)
642
+ via ||= :all
633
643
 
634
- match(path, { to: app, anchor: false, format: false }.merge(options))
644
+ match(path_or_action, to: app, as:, via:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, &block)
635
645
 
636
646
  define_generate_prefix(app, target_as) if rails_app
637
647
  self
@@ -643,7 +653,7 @@ module ActionDispatch
643
653
  alias_method :default_url_options, :default_url_options=
644
654
 
645
655
  def with_default_scope(scope, &block)
646
- scope(scope) do
656
+ scope(**scope) do
647
657
  instance_exec(&block)
648
658
  end
649
659
  end
@@ -654,6 +664,24 @@ module ActionDispatch
654
664
  end
655
665
 
656
666
  private
667
+ def assign_deprecated_option(deprecated_options, key, method_name)
668
+ if (deprecated_value = deprecated_options.delete(key))
669
+ ActionDispatch.deprecator.warn(<<~MSG.squish)
670
+ #{method_name} received a hash argument #{key}. Please use a keyword instead. Support to hash argument will be removed in Rails 8.2.
671
+ MSG
672
+ deprecated_value
673
+ end
674
+ end
675
+
676
+ def assign_deprecated_options(deprecated_options, options, method_name)
677
+ deprecated_options.each do |key, value|
678
+ ActionDispatch.deprecator.warn(<<~MSG.squish)
679
+ #{method_name} received a hash argument #{key}. Please use a keyword instead. Support to hash argument will be removed in Rails 8.2.
680
+ MSG
681
+ options[key] = value
682
+ end
683
+ end
684
+
657
685
  def rails_app?(app)
658
686
  app.is_a?(Class) && app < Rails::Railtie
659
687
  end
@@ -707,48 +735,144 @@ module ActionDispatch
707
735
  # [match](rdoc-ref:Base#match)
708
736
  #
709
737
  # get 'bacon', to: 'food#bacon'
710
- def get(*args, &block)
711
- map_method(:get, args, &block)
738
+ def get(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: nil, format: nil, path: nil, internal: nil, **mapping, &block)
739
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
740
+ as = assign_deprecated_option(deprecated_options, :as, :get) if deprecated_options.key?(:as)
741
+ to ||= assign_deprecated_option(deprecated_options, :to, :get)
742
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :get)
743
+ action ||= assign_deprecated_option(deprecated_options, :action, :get)
744
+ on ||= assign_deprecated_option(deprecated_options, :on, :get)
745
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :get)
746
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :get)
747
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :get) if deprecated_options.key?(:anchor)
748
+ format = assign_deprecated_option(deprecated_options, :format, :get) if deprecated_options.key?(:format)
749
+ path ||= assign_deprecated_option(deprecated_options, :path, :get)
750
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :get)
751
+ assign_deprecated_options(deprecated_options, mapping, :get)
752
+ end
753
+
754
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: :get, &block)
755
+ self
712
756
  end
713
757
 
714
758
  # Define a route that only recognizes HTTP POST. For supported arguments, see
715
759
  # [match](rdoc-ref:Base#match)
716
760
  #
717
761
  # post 'bacon', to: 'food#bacon'
718
- def post(*args, &block)
719
- map_method(:post, args, &block)
762
+ def post(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: nil, format: nil, path: nil, internal: nil, **mapping, &block)
763
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
764
+ as = assign_deprecated_option(deprecated_options, :as, :post) if deprecated_options.key?(:as)
765
+ to ||= assign_deprecated_option(deprecated_options, :to, :post)
766
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :post)
767
+ action ||= assign_deprecated_option(deprecated_options, :action, :post)
768
+ on ||= assign_deprecated_option(deprecated_options, :on, :post)
769
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :post)
770
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :post)
771
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :post) if deprecated_options.key?(:anchor)
772
+ format = assign_deprecated_option(deprecated_options, :format, :post) if deprecated_options.key?(:format)
773
+ path ||= assign_deprecated_option(deprecated_options, :path, :post)
774
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :post)
775
+ assign_deprecated_options(deprecated_options, mapping, :post)
776
+ end
777
+
778
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: :post, &block)
779
+ self
720
780
  end
721
781
 
722
782
  # Define a route that only recognizes HTTP PATCH. For supported arguments, see
723
783
  # [match](rdoc-ref:Base#match)
724
784
  #
725
785
  # patch 'bacon', to: 'food#bacon'
726
- def patch(*args, &block)
727
- map_method(:patch, args, &block)
786
+ def patch(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: nil, format: nil, path: nil, internal: nil, **mapping, &block)
787
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
788
+ as = assign_deprecated_option(deprecated_options, :as, :patch) if deprecated_options.key?(:as)
789
+ to ||= assign_deprecated_option(deprecated_options, :to, :patch)
790
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :patch)
791
+ action ||= assign_deprecated_option(deprecated_options, :action, :patch)
792
+ on ||= assign_deprecated_option(deprecated_options, :on, :patch)
793
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :patch)
794
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :patch)
795
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :patch) if deprecated_options.key?(:anchor)
796
+ format = assign_deprecated_option(deprecated_options, :format, :patch) if deprecated_options.key?(:format)
797
+ path ||= assign_deprecated_option(deprecated_options, :path, :patch)
798
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :patch)
799
+ assign_deprecated_options(deprecated_options, mapping, :patch)
800
+ end
801
+
802
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: :patch, &block)
803
+ self
728
804
  end
729
805
 
730
806
  # Define a route that only recognizes HTTP PUT. For supported arguments, see
731
807
  # [match](rdoc-ref:Base#match)
732
808
  #
733
809
  # put 'bacon', to: 'food#bacon'
734
- def put(*args, &block)
735
- map_method(:put, args, &block)
810
+ def put(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: nil, format: nil, path: nil, internal: nil, **mapping, &block)
811
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
812
+ as = assign_deprecated_option(deprecated_options, :as, :put) if deprecated_options.key?(:as)
813
+ to ||= assign_deprecated_option(deprecated_options, :to, :put)
814
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :put)
815
+ action ||= assign_deprecated_option(deprecated_options, :action, :put)
816
+ on ||= assign_deprecated_option(deprecated_options, :on, :put)
817
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :put)
818
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :put)
819
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :put) if deprecated_options.key?(:anchor)
820
+ format = assign_deprecated_option(deprecated_options, :format, :put) if deprecated_options.key?(:format)
821
+ path ||= assign_deprecated_option(deprecated_options, :path, :put)
822
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :put)
823
+ assign_deprecated_options(deprecated_options, mapping, :put)
824
+ end
825
+
826
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: :put, &block)
827
+ self
736
828
  end
737
829
 
738
830
  # Define a route that only recognizes HTTP DELETE. For supported arguments, see
739
831
  # [match](rdoc-ref:Base#match)
740
832
  #
741
833
  # delete 'broccoli', to: 'food#broccoli'
742
- def delete(*args, &block)
743
- map_method(:delete, args, &block)
834
+ def delete(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: nil, format: nil, path: nil, internal: nil, **mapping, &block)
835
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
836
+ as = assign_deprecated_option(deprecated_options, :as, :delete) if deprecated_options.key?(:as)
837
+ to ||= assign_deprecated_option(deprecated_options, :to, :delete)
838
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :delete)
839
+ action ||= assign_deprecated_option(deprecated_options, :action, :delete)
840
+ on ||= assign_deprecated_option(deprecated_options, :on, :delete)
841
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :delete)
842
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :delete)
843
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :delete) if deprecated_options.key?(:anchor)
844
+ format = assign_deprecated_option(deprecated_options, :format, :delete) if deprecated_options.key?(:format)
845
+ path ||= assign_deprecated_option(deprecated_options, :path, :delete)
846
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :delete)
847
+ assign_deprecated_options(deprecated_options, mapping, :delete)
848
+ end
849
+
850
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: :delete, &block)
851
+ self
744
852
  end
745
853
 
746
854
  # Define a route that only recognizes HTTP OPTIONS. For supported arguments, see
747
855
  # [match](rdoc-ref:Base#match)
748
856
  #
749
857
  # options 'carrots', to: 'food#carrots'
750
- def options(*args, &block)
751
- map_method(:options, args, &block)
858
+ def options(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: false, format: false, path: nil, internal: nil, **mapping, &block)
859
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
860
+ as = assign_deprecated_option(deprecated_options, :as, :options) if deprecated_options.key?(:as)
861
+ to ||= assign_deprecated_option(deprecated_options, :to, :options)
862
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :options)
863
+ action ||= assign_deprecated_option(deprecated_options, :action, :options)
864
+ on ||= assign_deprecated_option(deprecated_options, :on, :options)
865
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :options)
866
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :options)
867
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :options) if deprecated_options.key?(:anchor)
868
+ format = assign_deprecated_option(deprecated_options, :format, :options) if deprecated_options.key?(:format)
869
+ path ||= assign_deprecated_option(deprecated_options, :path, :options)
870
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :options)
871
+ assign_deprecated_options(deprecated_options, mapping, :options)
872
+ end
873
+
874
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: :options, &block)
875
+ self
752
876
  end
753
877
 
754
878
  # Define a route that recognizes HTTP CONNECT (and GET) requests. More
@@ -757,17 +881,25 @@ module ActionDispatch
757
881
  # see [match](rdoc-ref:Base#match)
758
882
  #
759
883
  # connect 'live', to: 'live#index'
760
- def connect(*args, &block)
761
- map_method([:get, :connect], args, &block)
884
+ def connect(*path_or_actions, as: DEFAULT, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: false, format: false, path: nil, internal: nil, **mapping, &block)
885
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
886
+ as = assign_deprecated_option(deprecated_options, :as, :connect) if deprecated_options.key?(:as)
887
+ to ||= assign_deprecated_option(deprecated_options, :to, :connect)
888
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :connect)
889
+ action ||= assign_deprecated_option(deprecated_options, :action, :connect)
890
+ on ||= assign_deprecated_option(deprecated_options, :on, :connect)
891
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :connect)
892
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :connect)
893
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :connect) if deprecated_options.key?(:anchor)
894
+ format = assign_deprecated_option(deprecated_options, :format, :connect) if deprecated_options.key?(:format)
895
+ path ||= assign_deprecated_option(deprecated_options, :path, :connect)
896
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :connect)
897
+ assign_deprecated_options(deprecated_options, mapping, :connect)
898
+ end
899
+
900
+ match(*path_or_actions, as:, to:, controller:, action:, on:, defaults:, constraints:, anchor:, format:, path:, internal:, **mapping, via: [:get, :connect], &block)
901
+ self
762
902
  end
763
-
764
- private
765
- def map_method(method, args, &block)
766
- options = args.extract_options!
767
- options[:via] = method
768
- match(*args, options, &block)
769
- self
770
- end
771
903
  end
772
904
 
773
905
  # You may wish to organize groups of controllers under a namespace. Most
@@ -854,8 +986,13 @@ module ActionDispatch
854
986
  # scope as: "sekret" do
855
987
  # resources :posts
856
988
  # end
857
- def scope(*args)
858
- options = args.extract_options!.dup
989
+ def scope(*args, only: nil, except: nil, **options)
990
+ if args.grep(Hash).any? && (deprecated_options = args.extract_options!)
991
+ only ||= assign_deprecated_option(deprecated_options, :only, :scope)
992
+ only ||= assign_deprecated_option(deprecated_options, :except, :scope)
993
+ assign_deprecated_options(deprecated_options, options, :scope)
994
+ end
995
+
859
996
  scope = {}
860
997
 
861
998
  options[:path] = args.flatten.join("/") if args.any?
@@ -876,9 +1013,8 @@ module ActionDispatch
876
1013
  block, options[:constraints] = options[:constraints], {}
877
1014
  end
878
1015
 
879
- if options.key?(:only) || options.key?(:except)
880
- scope[:action_options] = { only: options.delete(:only),
881
- except: options.delete(:except) }
1016
+ if only || except
1017
+ scope[:action_options] = { only:, except: }
882
1018
  end
883
1019
 
884
1020
  if options.key? :anchor
@@ -958,18 +1094,24 @@ module ActionDispatch
958
1094
  # namespace :admin, as: "sekret" do
959
1095
  # resources :posts
960
1096
  # end
961
- def namespace(path, options = {}, &block)
962
- path = path.to_s
963
-
964
- defaults = {
965
- module: path,
966
- as: options.fetch(:as, path),
967
- shallow_path: options.fetch(:path, path),
968
- shallow_prefix: options.fetch(:as, path)
969
- }
1097
+ def namespace(name, deprecated_options = nil, as: DEFAULT, path: DEFAULT, shallow_path: DEFAULT, shallow_prefix: DEFAULT, **options, &block)
1098
+ if deprecated_options.is_a?(Hash)
1099
+ as = assign_deprecated_option(deprecated_options, :as, :namespace) if deprecated_options.key?(:as)
1100
+ path ||= assign_deprecated_option(deprecated_options, :path, :namespace) if deprecated_options.key?(:path)
1101
+ shallow_path ||= assign_deprecated_option(deprecated_options, :shallow_path, :namespace) if deprecated_options.key?(:shallow_path)
1102
+ shallow_prefix ||= assign_deprecated_option(deprecated_options, :shallow_prefix, :namespace) if deprecated_options.key?(:shallow_prefix)
1103
+ assign_deprecated_options(deprecated_options, options, :namespace)
1104
+ end
970
1105
 
971
- path_scope(options.delete(:path) { path }) do
972
- scope(defaults.merge!(options), &block)
1106
+ name = name.to_s
1107
+ options[:module] ||= name
1108
+ as = name if as == DEFAULT
1109
+ path = name if path == DEFAULT
1110
+ shallow_path = path if shallow_path == DEFAULT
1111
+ shallow_prefix = as if shallow_prefix == DEFAULT
1112
+
1113
+ path_scope(path) do
1114
+ scope(**options, as:, shallow_path:, shallow_prefix:, &block)
973
1115
  end
974
1116
  end
975
1117
 
@@ -1174,13 +1316,13 @@ module ActionDispatch
1174
1316
 
1175
1317
  attr_reader :controller, :path, :param
1176
1318
 
1177
- def initialize(entities, api_only, shallow, options = {})
1319
+ def initialize(entities, api_only, shallow, only: nil, except: nil, **options)
1178
1320
  if options[:param].to_s.include?(":")
1179
1321
  raise ArgumentError, ":param option can't contain colons"
1180
1322
  end
1181
1323
 
1182
1324
  valid_actions = self.class.default_actions(false) # ignore api_only for this validation
1183
- if invalid_actions = invalid_only_except_options(options, valid_actions).presence
1325
+ if (invalid_actions = invalid_only_except_options(valid_actions, only:, except:).presence)
1184
1326
  error_prefix = "Route `resource#{"s" unless singleton?} :#{entities}`"
1185
1327
  raise ArgumentError, "#{error_prefix} - :only and :except must include only #{valid_actions}, but also included #{invalid_actions}"
1186
1328
  end
@@ -1193,8 +1335,8 @@ module ActionDispatch
1193
1335
  @options = options
1194
1336
  @shallow = shallow
1195
1337
  @api_only = api_only
1196
- @only = options.delete :only
1197
- @except = options.delete :except
1338
+ @only = only
1339
+ @except = except
1198
1340
  end
1199
1341
 
1200
1342
  def default_actions
@@ -1268,8 +1410,8 @@ module ActionDispatch
1268
1410
  def singleton?; false; end
1269
1411
 
1270
1412
  private
1271
- def invalid_only_except_options(options, valid_actions)
1272
- options.values_at(:only, :except).flatten.compact.uniq.map(&:to_sym) - valid_actions
1413
+ def invalid_only_except_options(valid_actions, only:, except:)
1414
+ [only, except].flatten.compact.uniq.map(&:to_sym) - valid_actions
1273
1415
  end
1274
1416
  end
1275
1417
 
@@ -1284,7 +1426,7 @@ module ActionDispatch
1284
1426
  end
1285
1427
  end
1286
1428
 
1287
- def initialize(entities, api_only, shallow, options)
1429
+ def initialize(entities, api_only, shallow, **options)
1288
1430
  super
1289
1431
  @as = nil
1290
1432
  @controller = (options[:controller] || plural).to_s
@@ -1345,19 +1487,22 @@ module ActionDispatch
1345
1487
  #
1346
1488
  # ### Options
1347
1489
  # Takes same options as [resources](rdoc-ref:#resources)
1348
- def resource(*resources, &block)
1349
- options = resources.extract_options!.dup
1490
+ def resource(*resources, concerns: nil, **options, &block)
1491
+ if resources.grep(Hash).any? && (deprecated_options = resources.extract_options!)
1492
+ concerns = assign_deprecated_option(deprecated_options, :concerns, :resource) if deprecated_options.key?(:concerns)
1493
+ assign_deprecated_options(deprecated_options, options, :resource)
1494
+ end
1350
1495
 
1351
- if apply_common_behavior_for(:resource, resources, options, &block)
1496
+ if apply_common_behavior_for(:resource, resources, concerns:, **options, &block)
1352
1497
  return self
1353
1498
  end
1354
1499
 
1355
1500
  with_scope_level(:resource) do
1356
1501
  options = apply_action_options :resource, options
1357
- resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do
1502
+ resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], **options)) do
1358
1503
  yield if block_given?
1359
1504
 
1360
- concerns(options[:concerns]) if options[:concerns]
1505
+ concerns(*concerns) if concerns
1361
1506
 
1362
1507
  new do
1363
1508
  get :new
@@ -1515,19 +1660,22 @@ module ActionDispatch
1515
1660
  #
1516
1661
  # # resource actions are at /admin/posts.
1517
1662
  # resources :posts, path: "admin/posts"
1518
- def resources(*resources, &block)
1519
- options = resources.extract_options!.dup
1663
+ def resources(*resources, concerns: nil, **options, &block)
1664
+ if resources.grep(Hash).any? && (deprecated_options = resources.extract_options!)
1665
+ concerns = assign_deprecated_option(deprecated_options, :concerns, :resources) if deprecated_options.key?(:concerns)
1666
+ assign_deprecated_options(deprecated_options, options, :resources)
1667
+ end
1520
1668
 
1521
- if apply_common_behavior_for(:resources, resources, options, &block)
1669
+ if apply_common_behavior_for(:resources, resources, concerns:, **options, &block)
1522
1670
  return self
1523
1671
  end
1524
1672
 
1525
1673
  with_scope_level(:resources) do
1526
1674
  options = apply_action_options :resources, options
1527
- resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
1675
+ resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], **options)) do
1528
1676
  yield if block_given?
1529
1677
 
1530
- concerns(options[:concerns]) if options[:concerns]
1678
+ concerns(*concerns) if concerns
1531
1679
 
1532
1680
  collection do
1533
1681
  get :index if parent_resource.actions.include?(:index)
@@ -1612,19 +1760,19 @@ module ActionDispatch
1612
1760
  if shallow? && shallow_nesting_depth >= 1
1613
1761
  shallow_scope do
1614
1762
  path_scope(parent_resource.nested_scope) do
1615
- scope(nested_options, &block)
1763
+ scope(**nested_options, &block)
1616
1764
  end
1617
1765
  end
1618
1766
  else
1619
1767
  path_scope(parent_resource.nested_scope) do
1620
- scope(nested_options, &block)
1768
+ scope(**nested_options, &block)
1621
1769
  end
1622
1770
  end
1623
1771
  end
1624
1772
  end
1625
1773
 
1626
1774
  # See ActionDispatch::Routing::Mapper::Scoping#namespace.
1627
- def namespace(path, options = {})
1775
+ def namespace(name, deprecated_options = nil, as: DEFAULT, path: DEFAULT, shallow_path: DEFAULT, shallow_prefix: DEFAULT, **options, &block)
1628
1776
  if resource_scope?
1629
1777
  nested { super }
1630
1778
  else
@@ -1685,38 +1833,57 @@ module ActionDispatch
1685
1833
  # [match](rdoc-ref:Base#match).
1686
1834
  #
1687
1835
  # match 'path', to: 'controller#action', via: :post
1688
- # match 'path', 'otherpath', on: :member, via: :get
1689
- def match(path, *rest, &block)
1690
- if rest.empty? && Hash === path
1691
- options = path
1692
- path, to = options.find { |name, _value| name.is_a?(String) }
1693
-
1694
- raise ArgumentError, "Route path not specified" if path.nil?
1836
+ # match 'otherpath', on: :member, via: :get
1837
+ def match(*path_or_actions, as: DEFAULT, via: nil, to: nil, controller: nil, action: nil, on: nil, defaults: nil, constraints: nil, anchor: nil, format: nil, path: nil, internal: nil, **mapping, &block)
1838
+ if path_or_actions.grep(Hash).any? && (deprecated_options = path_or_actions.extract_options!)
1839
+ as = assign_deprecated_option(deprecated_options, :as, :match) if deprecated_options.key?(:as)
1840
+ via ||= assign_deprecated_option(deprecated_options, :via, :match)
1841
+ to ||= assign_deprecated_option(deprecated_options, :to, :match)
1842
+ controller ||= assign_deprecated_option(deprecated_options, :controller, :match)
1843
+ action ||= assign_deprecated_option(deprecated_options, :action, :match)
1844
+ on ||= assign_deprecated_option(deprecated_options, :on, :match)
1845
+ defaults ||= assign_deprecated_option(deprecated_options, :defaults, :match)
1846
+ constraints ||= assign_deprecated_option(deprecated_options, :constraints, :match)
1847
+ anchor = assign_deprecated_option(deprecated_options, :anchor, :match) if deprecated_options.key?(:anchor)
1848
+ format = assign_deprecated_option(deprecated_options, :format, :match) if deprecated_options.key?(:format)
1849
+ path ||= assign_deprecated_option(deprecated_options, :path, :match)
1850
+ internal ||= assign_deprecated_option(deprecated_options, :internal, :match)
1851
+ assign_deprecated_options(deprecated_options, mapping, :match)
1852
+ end
1853
+
1854
+ raise ArgumentError, "Wrong number of arguments (expect 1, got #{path_or_actions.count})" if path_or_actions.count > 1
1855
+
1856
+ if path_or_actions.none? && mapping.any?
1857
+ hash_path, hash_to = mapping.find { |key, _| key.is_a?(String) }
1858
+ if hash_path.nil?
1859
+ raise ArgumentError, "Route path not specified"
1860
+ else
1861
+ mapping.delete(hash_path)
1862
+ end
1695
1863
 
1696
- case to
1697
- when Symbol
1698
- options[:action] = to
1699
- when String
1700
- if to.include?("#")
1701
- options[:to] = to
1864
+ if hash_path
1865
+ path_or_actions.push hash_path
1866
+ case hash_to
1867
+ when Symbol
1868
+ action ||= hash_to
1869
+ when String
1870
+ if hash_to.include?("#")
1871
+ to ||= hash_to
1872
+ else
1873
+ controller ||= hash_to
1874
+ end
1702
1875
  else
1703
- options[:controller] = to
1876
+ to ||= hash_to
1704
1877
  end
1705
- else
1706
- options[:to] = to
1707
1878
  end
1708
-
1709
- options.delete(path)
1710
- paths = [path]
1711
- else
1712
- options = rest.pop || {}
1713
- paths = [path] + rest
1714
1879
  end
1715
1880
 
1716
- if options.key?(:defaults)
1717
- defaults(options.delete(:defaults)) { map_match(paths, options, &block) }
1718
- else
1719
- map_match(paths, options, &block)
1881
+ path_or_actions.each do |path_or_action|
1882
+ if defaults
1883
+ defaults(defaults) { map_match(path_or_action, as:, via:, to:, controller:, action:, on:, constraints:, anchor:, format:, path:, internal:, mapping:, &block) }
1884
+ else
1885
+ map_match(path_or_action, as:, via:, to:, controller:, action:, on:, constraints:, anchor:, format:, path:, internal:, mapping:, &block)
1886
+ end
1720
1887
  end
1721
1888
  end
1722
1889
 
@@ -1758,22 +1925,21 @@ module ActionDispatch
1758
1925
  @scope[:scope_level_resource]
1759
1926
  end
1760
1927
 
1761
- def apply_common_behavior_for(method, resources, options, &block)
1928
+ def apply_common_behavior_for(method, resources, shallow: nil, **options, &block)
1762
1929
  if resources.length > 1
1763
- resources.each { |r| public_send(method, r, options, &block) }
1930
+ resources.each { |r| public_send(method, r, shallow:, **options, &block) }
1764
1931
  return true
1765
1932
  end
1766
1933
 
1767
- if options[:shallow]
1768
- options.delete(:shallow)
1769
- shallow do
1770
- public_send(method, resources.pop, options, &block)
1934
+ if shallow
1935
+ self.shallow do
1936
+ public_send(method, resources.pop, **options, &block)
1771
1937
  end
1772
1938
  return true
1773
1939
  end
1774
1940
 
1775
1941
  if resource_scope?
1776
- nested { public_send(method, resources.pop, options, &block) }
1942
+ nested { public_send(method, resources.pop, shallow:, **options, &block) }
1777
1943
  return true
1778
1944
  end
1779
1945
 
@@ -1782,9 +1948,9 @@ module ActionDispatch
1782
1948
  end
1783
1949
 
1784
1950
  scope_options = options.slice!(*RESOURCE_OPTIONS)
1785
- unless scope_options.empty?
1786
- scope(scope_options) do
1787
- public_send(method, resources.pop, options, &block)
1951
+ if !scope_options.empty? || !shallow.nil?
1952
+ scope(**scope_options, shallow:) do
1953
+ public_send(method, resources.pop, **options, &block)
1788
1954
  end
1789
1955
  return true
1790
1956
  end
@@ -1875,9 +2041,10 @@ module ActionDispatch
1875
2041
  end
1876
2042
 
1877
2043
  def shallow_scope
1878
- scope = { as: @scope[:shallow_prefix],
1879
- path: @scope[:shallow_path] }
1880
- @scope = @scope.new scope
2044
+ @scope = @scope.new(
2045
+ as: @scope[:shallow_prefix],
2046
+ path: @scope[:shallow_path],
2047
+ )
1881
2048
 
1882
2049
  yield
1883
2050
  ensure
@@ -1899,7 +2066,7 @@ module ActionDispatch
1899
2066
  end
1900
2067
 
1901
2068
  def prefix_name_for_action(as, action)
1902
- if as
2069
+ if as && as != DEFAULT
1903
2070
  prefix = as
1904
2071
  elsif !canonical_action?(action)
1905
2072
  prefix = action
@@ -1915,7 +2082,7 @@ module ActionDispatch
1915
2082
  name_prefix = @scope[:as]
1916
2083
 
1917
2084
  if parent_resource
1918
- return nil unless as || action
2085
+ return nil unless as != DEFAULT || action
1919
2086
 
1920
2087
  collection_name = parent_resource.collection_name
1921
2088
  member_name = parent_resource.member_name
@@ -1928,7 +2095,7 @@ module ActionDispatch
1928
2095
  # If a name was not explicitly given, we check if it is valid and return nil in
1929
2096
  # case it isn't. Otherwise, we pass the invalid name forward so the underlying
1930
2097
  # router engine treats it and raises an exception.
1931
- if as.nil?
2098
+ if as == DEFAULT
1932
2099
  candidate unless !candidate.match?(/\A[_a-z]/i) || has_named_route?(candidate)
1933
2100
  else
1934
2101
  candidate
@@ -1959,47 +2126,35 @@ module ActionDispatch
1959
2126
  @scope = @scope.parent
1960
2127
  end
1961
2128
 
1962
- def map_match(paths, options)
1963
- ActionDispatch.deprecator.warn(<<-MSG.squish) if paths.count > 1
1964
- Mapping a route with multiple paths is deprecated and
1965
- will be removed in Rails 8.1. Please use multiple method calls instead.
1966
- MSG
1967
-
1968
- if (on = options[:on]) && !VALID_ON_OPTIONS.include?(on)
2129
+ def map_match(path_or_action, constraints: nil, anchor: nil, format: nil, path: nil, as: DEFAULT, via: nil, to: nil, controller: nil, action: nil, on: nil, internal: nil, mapping: nil)
2130
+ if on && !VALID_ON_OPTIONS.include?(on)
1969
2131
  raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
1970
2132
  end
1971
2133
 
1972
2134
  if @scope[:to]
1973
- options[:to] ||= @scope[:to]
2135
+ to ||= @scope[:to]
1974
2136
  end
1975
2137
 
1976
2138
  if @scope[:controller] && @scope[:action]
1977
- options[:to] ||= "#{@scope[:controller]}##{@scope[:action]}"
2139
+ to ||= "#{@scope[:controller]}##{@scope[:action]}"
1978
2140
  end
1979
2141
 
1980
- controller = options.delete(:controller) || @scope[:controller]
1981
- option_path = options.delete :path
1982
- to = options.delete :to
1983
- via = Mapping.check_via Array(options.delete(:via) {
1984
- @scope[:via]
1985
- })
1986
- formatted = options.delete(:format) { @scope[:format] }
1987
- anchor = options.delete(:anchor) { true }
1988
- options_constraints = options.delete(:constraints) || {}
1989
-
1990
- path_types = paths.group_by(&:class)
1991
- (path_types[String] || []).each do |_path|
1992
- route_options = options.dup
1993
- if _path && option_path
2142
+ controller ||= @scope[:controller]
2143
+ via = Mapping.check_via Array(via || @scope[:via])
2144
+ format ||= @scope[:format] if format.nil?
2145
+ anchor ||= true if anchor.nil?
2146
+ constraints ||= {}
2147
+
2148
+ case path_or_action
2149
+ when String
2150
+ if path_or_action && path
1994
2151
  raise ArgumentError, "Ambiguous route definition. Both :path and the route path were specified as strings."
1995
2152
  end
1996
- to = get_to_from_path(_path, to, route_options[:action])
1997
- decomposed_match(_path, controller, route_options, _path, to, via, formatted, anchor, options_constraints)
1998
- end
1999
-
2000
- (path_types[Symbol] || []).each do |action|
2001
- route_options = options.dup
2002
- decomposed_match(action, controller, route_options, option_path, to, via, formatted, anchor, options_constraints)
2153
+ path = path_or_action
2154
+ to = get_to_from_path(path_or_action, to, action)
2155
+ decomposed_match(path, controller, as, action, path, to, via, format, anchor, constraints, internal, mapping, on)
2156
+ when Symbol
2157
+ decomposed_match(path_or_action, controller, as, action, path, to, via, format, anchor, constraints, internal, mapping, on)
2003
2158
  end
2004
2159
 
2005
2160
  self
@@ -2020,28 +2175,28 @@ module ActionDispatch
2020
2175
  %r{^/?[-\w]+/[-\w/]+$}.match?(path)
2021
2176
  end
2022
2177
 
2023
- def decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints)
2024
- if on = options.delete(:on)
2025
- send(on) { decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints) }
2178
+ def decomposed_match(path, controller, as, action, _path, to, via, formatted, anchor, options_constraints, internal, options_mapping, on = nil)
2179
+ if on
2180
+ send(on) { decomposed_match(path, controller, as, action, _path, to, via, formatted, anchor, options_constraints, internal, options_mapping) }
2026
2181
  else
2027
2182
  case @scope.scope_level
2028
2183
  when :resources
2029
- nested { decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints) }
2184
+ nested { decomposed_match(path, controller, as, action, _path, to, via, formatted, anchor, options_constraints, internal, options_mapping) }
2030
2185
  when :resource
2031
- member { decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints) }
2186
+ member { decomposed_match(path, controller, as, action, _path, to, via, formatted, anchor, options_constraints, internal, options_mapping) }
2032
2187
  else
2033
- add_route(path, controller, options, _path, to, via, formatted, anchor, options_constraints)
2188
+ add_route(path, controller, as, action, _path, to, via, formatted, anchor, options_constraints, internal, options_mapping)
2034
2189
  end
2035
2190
  end
2036
2191
  end
2037
2192
 
2038
- def add_route(action, controller, options, _path, to, via, formatted, anchor, options_constraints)
2193
+ def add_route(action, controller, as, options_action, _path, to, via, formatted, anchor, options_constraints, internal, options_mapping)
2039
2194
  path = path_for_action(action, _path)
2040
2195
  raise ArgumentError, "path is required" if path.blank?
2041
2196
 
2042
2197
  action = action.to_s
2043
2198
 
2044
- default_action = options.delete(:action) || @scope[:action]
2199
+ default_action = options_action || @scope[:action]
2045
2200
 
2046
2201
  if /^[\w\-\/]+$/.match?(action)
2047
2202
  default_action ||= action.tr("-", "_") unless action.include?("/")
@@ -2049,22 +2204,16 @@ module ActionDispatch
2049
2204
  action = nil
2050
2205
  end
2051
2206
 
2052
- as = if !options.fetch(:as, true) # if it's set to nil or false
2053
- options.delete(:as)
2054
- else
2055
- name_for_action(options.delete(:as), action)
2056
- end
2057
-
2207
+ as = name_for_action(as, action) if as
2058
2208
  path = Mapping.normalize_path URI::RFC2396_PARSER.escape(path), formatted
2059
- ast = Journey::Parser.parse path
2209
+ ast = Journey::Parser.parse path
2060
2210
 
2061
- mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
2211
+ mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, internal, options_mapping)
2062
2212
  @set.add_route(mapping, as)
2063
2213
  end
2064
2214
 
2065
2215
  def match_root_route(options)
2066
- args = ["/", { as: :root, via: :get }.merge(options)]
2067
- match(*args)
2216
+ match("/", as: :root, via: :get, **options)
2068
2217
  end
2069
2218
  end
2070
2219
 
@@ -2159,8 +2308,7 @@ module ActionDispatch
2159
2308
  # namespace :posts do
2160
2309
  # concerns :commentable
2161
2310
  # end
2162
- def concerns(*args)
2163
- options = args.extract_options!
2311
+ def concerns(*args, **options)
2164
2312
  args.flatten.each do |name|
2165
2313
  if concern = @concerns[name]
2166
2314
  concern.call(self, options)
@@ -2375,6 +2523,8 @@ module ActionDispatch
2375
2523
  ROOT = Scope.new({}, nil)
2376
2524
  end
2377
2525
 
2526
+ DEFAULT = Object.new # :nodoc:
2527
+
2378
2528
  def initialize(set) # :nodoc:
2379
2529
  @set = set
2380
2530
  @draw_paths = set.draw_paths