From 36ff424c3b122efee47fe11b084d0bee3d974b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Barri=C3=A9?= Date: Tue, 9 Apr 2024 13:47:43 +0200 Subject: [PATCH] Restore to: option with an implicit controller The `:to` option for routes can once again be a String without a controller if the controller is implicitly provided by a nesting `controller` or `resources` call. --- actionpack/CHANGELOG.md | 12 ++++++++++++ actionpack/lib/action_dispatch/routing/mapper.rb | 15 ++++++++++----- actionpack/test/dispatch/routing_test.rb | 14 ++++++++++++-- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index f86b51e6393e5..98e8abb1c8177 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,15 @@ +* Fix a regression in 7.1.3 passing a `to:` option without a controller when the controller is already defined by a scope. + + ```ruby + Rails.application.routes.draw do + controller :home do + get "recent", to: "recent_posts" + end + end + ``` + + *Étienne Barrié* + * Request Forgery takes relative paths into account. *Stefan Wienert* diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 724bf72e5c508..317e8886f6258 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -231,12 +231,17 @@ def normalize_options!(options, path_params, modyoule) if to.nil? controller = default_controller action = default_action - elsif to.is_a?(String) && to.include?("#") - to_endpoint = to.split("#").map!(&:-@) - controller = to_endpoint[0] - action = to_endpoint[1] + elsif to.is_a?(String) + if to.include?("#") + to_endpoint = to.split("#").map!(&:-@) + controller = to_endpoint[0] + action = to_endpoint[1] + else + controller = default_controller + action = to + end else - raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#'" + raise ArgumentError, ":to must respond to `action` or `call`, or it must be a String that includes '#', or the controller should be implicit" end controller = add_controller_module(controller, modyoule) diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 460cd1aa10c5d..7d396f0c05d15 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -4037,6 +4037,7 @@ def draw(&block) routes = ActionDispatch::Routing::RouteSet.new routes.draw(&block) @app = self.class.build_app routes + @routes = routes end def test_missing_controller @@ -4054,7 +4055,16 @@ def test_missing_controller_with_to get "/foo/bar", to: "foo" end } - assert_match(/:to must respond to/, ex.message) + assert_match(/Missing :controller/, ex.message) + end + + def test_implicit_controller_with_to + draw do + controller :foo do + get "/foo/bar", to: "bar" + end + end + assert_routing "/foo/bar", controller: "foo", action: "bar" end def test_to_is_a_symbol @@ -4066,7 +4076,7 @@ def test_to_is_a_symbol assert_match(/:to must respond to/, ex.message) end - def test_missing_action_on_hash + def test_missing_action_with_to ex = assert_raises(ArgumentError) { draw do get "/foo/bar", to: "foo#"