Skip to content

Commit f4b581b

Browse files
committed
Use keywords in routing scopes and resources
Converts hashes to keywords in ActionDispatch::Resources::Resource and in ActionDispatch::Scope to match syntax of other mapping methods and allocate less.
1 parent eaa74ee commit f4b581b

File tree

4 files changed

+49
-60
lines changed

4 files changed

+49
-60
lines changed

actionpack/lib/action_dispatch/routing/mapper.rb

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ def default_url_options=(options)
673673
alias_method :default_url_options, :default_url_options=
674674

675675
def with_default_scope(scope, &block)
676-
scope(scope) do
676+
scope(**scope) do
677677
instance_exec(&block)
678678
end
679679
end
@@ -872,8 +872,7 @@ module Scoping
872872
# scope as: "sekret" do
873873
# resources :posts
874874
# end
875-
def scope(*args)
876-
options = args.extract_options!.dup
875+
def scope(*args, only: nil, except: nil, **options)
877876
scope = {}
878877

879878
options[:path] = args.flatten.join("/") if args.any?
@@ -894,9 +893,8 @@ def scope(*args)
894893
block, options[:constraints] = options[:constraints], {}
895894
end
896895

897-
if options.key?(:only) || options.key?(:except)
898-
scope[:action_options] = { only: options.delete(:only),
899-
except: options.delete(:except) }
896+
if only || except
897+
scope[:action_options] = { only:, except: }
900898
end
901899

902900
if options.key? :anchor
@@ -976,18 +974,16 @@ def controller(controller)
976974
# namespace :admin, as: "sekret" do
977975
# resources :posts
978976
# end
979-
def namespace(path, options = {}, &block)
980-
path = path.to_s
981-
982-
defaults = {
983-
module: path,
984-
as: options.fetch(:as, path),
985-
shallow_path: options.fetch(:path, path),
986-
shallow_prefix: options.fetch(:as, path)
987-
}
977+
def namespace(name, as: DEFAULT, path: DEFAULT, shallow_path: DEFAULT, shallow_prefix: DEFAULT, **options, &block)
978+
name = name.to_s
979+
options[:module] ||= name
980+
as = name if as == DEFAULT
981+
path = name if path == DEFAULT
982+
shallow_path = path if shallow_path == DEFAULT
983+
shallow_prefix = as if shallow_prefix == DEFAULT
988984

989-
path_scope(options.delete(:path) { path }) do
990-
scope(defaults.merge!(options), &block)
985+
path_scope(path) do
986+
scope(**options, as:, shallow_path:, shallow_prefix:, &block)
991987
end
992988
end
993989

@@ -1181,7 +1177,7 @@ module Resources
11811177
class Resource # :nodoc:
11821178
attr_reader :controller, :path, :param
11831179

1184-
def initialize(entities, api_only, shallow, options = {})
1180+
def initialize(entities, api_only, shallow, only: nil, except: nil, **options)
11851181
if options[:param].to_s.include?(":")
11861182
raise ArgumentError, ":param option can't contain colons"
11871183
end
@@ -1194,8 +1190,8 @@ def initialize(entities, api_only, shallow, options = {})
11941190
@options = options
11951191
@shallow = shallow
11961192
@api_only = api_only
1197-
@only = options.delete :only
1198-
@except = options.delete :except
1193+
@only = only
1194+
@except = except
11991195
end
12001196

12011197
def default_actions
@@ -1274,7 +1270,7 @@ def singleton?; false; end
12741270
end
12751271

12761272
class SingletonResource < Resource # :nodoc:
1277-
def initialize(entities, api_only, shallow, options)
1273+
def initialize(entities, api_only, shallow, **options)
12781274
super
12791275
@as = nil
12801276
@controller = (options[:controller] || plural).to_s
@@ -1339,19 +1335,17 @@ def resources_path_names(options)
13391335
#
13401336
# ### Options
13411337
# Takes same options as [resources](rdoc-ref:#resources)
1342-
def resource(*resources, &block)
1343-
options = resources.extract_options!.dup
1344-
1345-
if apply_common_behavior_for(:resource, resources, options, &block)
1338+
def resource(*resources, concerns: nil, **options, &block)
1339+
if apply_common_behavior_for(:resource, resources, concerns:, **options, &block)
13461340
return self
13471341
end
13481342

13491343
with_scope_level(:resource) do
13501344
options = apply_action_options options
1351-
resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do
1345+
resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], **options)) do
13521346
yield if block_given?
13531347

1354-
concerns(options[:concerns]) if options[:concerns]
1348+
concerns(*concerns) if concerns
13551349

13561350
new do
13571351
get :new
@@ -1509,19 +1503,17 @@ def resource(*resources, &block)
15091503
#
15101504
# # resource actions are at /admin/posts.
15111505
# resources :posts, path: "admin/posts"
1512-
def resources(*resources, &block)
1513-
options = resources.extract_options!.dup
1514-
1515-
if apply_common_behavior_for(:resources, resources, options, &block)
1506+
def resources(*resources, concerns: nil, **options, &block)
1507+
if apply_common_behavior_for(:resources, resources, concerns:, **options, &block)
15161508
return self
15171509
end
15181510

15191511
with_scope_level(:resources) do
15201512
options = apply_action_options options
1521-
resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
1513+
resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], **options)) do
15221514
yield if block_given?
15231515

1524-
concerns(options[:concerns]) if options[:concerns]
1516+
concerns(*concerns) if concerns
15251517

15261518
collection do
15271519
get :index if parent_resource.actions.include?(:index)
@@ -1606,19 +1598,19 @@ def nested(&block)
16061598
if shallow? && shallow_nesting_depth >= 1
16071599
shallow_scope do
16081600
path_scope(parent_resource.nested_scope) do
1609-
scope(nested_options, &block)
1601+
scope(**nested_options, &block)
16101602
end
16111603
end
16121604
else
16131605
path_scope(parent_resource.nested_scope) do
1614-
scope(nested_options, &block)
1606+
scope(**nested_options, &block)
16151607
end
16161608
end
16171609
end
16181610
end
16191611

16201612
# See ActionDispatch::Routing::Mapper::Scoping#namespace.
1621-
def namespace(path, options = {})
1613+
def namespace(name, as: DEFAULT, path: DEFAULT, shallow_path: DEFAULT, shallow_prefix: DEFAULT, **options, &block)
16221614
if resource_scope?
16231615
nested { super }
16241616
else
@@ -1773,22 +1765,21 @@ def parent_resource
17731765
@scope[:scope_level_resource]
17741766
end
17751767

1776-
def apply_common_behavior_for(method, resources, options, &block)
1768+
def apply_common_behavior_for(method, resources, shallow: nil, **options, &block)
17771769
if resources.length > 1
1778-
resources.each { |r| public_send(method, r, options, &block) }
1770+
resources.each { |r| public_send(method, r, shallow:, **options, &block) }
17791771
return true
17801772
end
17811773

1782-
if options[:shallow]
1783-
options.delete(:shallow)
1784-
shallow do
1785-
public_send(method, resources.pop, options, &block)
1774+
if shallow
1775+
self.shallow do
1776+
public_send(method, resources.pop, **options, &block)
17861777
end
17871778
return true
17881779
end
17891780

17901781
if resource_scope?
1791-
nested { public_send(method, resources.pop, options, &block) }
1782+
nested { public_send(method, resources.pop, shallow:, **options, &block) }
17921783
return true
17931784
end
17941785

@@ -1797,9 +1788,9 @@ def apply_common_behavior_for(method, resources, options, &block)
17971788
end
17981789

17991790
scope_options = options.slice!(*RESOURCE_OPTIONS)
1800-
unless scope_options.empty?
1801-
scope(scope_options) do
1802-
public_send(method, resources.pop, options, &block)
1791+
if !scope_options.empty? || !shallow.nil?
1792+
scope(**scope_options, shallow:) do
1793+
public_send(method, resources.pop, **options, &block)
18031794
end
18041795
return true
18051796
end
@@ -1875,9 +1866,10 @@ def canonical_action?(action)
18751866
end
18761867

18771868
def shallow_scope
1878-
scope = { as: @scope[:shallow_prefix],
1879-
path: @scope[:shallow_path] }
1880-
@scope = @scope.new scope
1869+
@scope = @scope.new(
1870+
as: @scope[:shallow_prefix],
1871+
path: @scope[:shallow_path],
1872+
)
18811873

18821874
yield
18831875
ensure
@@ -2141,8 +2133,7 @@ def concern(name, callable = nil, &block)
21412133
# namespace :posts do
21422134
# concerns :commentable
21432135
# end
2144-
def concerns(*args)
2145-
options = args.extract_options!
2136+
def concerns(*args, **options)
21462137
args.flatten.each do |name|
21472138
if concern = @concerns[name]
21482139
concern.call(self, options)

actionpack/test/controller/resources_test.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def test_multiple_default_restful_routes
7777
def test_multiple_resources_with_options
7878
expected_options = { controller: "threads", action: "index" }
7979

80-
with_restful_routing :messages, :comments, expected_options.slice(:controller) do
80+
with_restful_routing :messages, :comments, controller: "threads" do
8181
assert_recognizes(expected_options, path: "comments")
8282
assert_recognizes(expected_options, path: "messages")
8383
end
@@ -1110,17 +1110,15 @@ def test_singleton_resource_name_is_not_singularized
11101110
end
11111111

11121112
private
1113-
def with_restful_routing(*args)
1114-
options = args.extract_options!
1113+
def with_restful_routing(*args, **options)
11151114
collection_methods = options.delete(:collection)
11161115
member_methods = options.delete(:member)
11171116
path_prefix = options.delete(:path_prefix)
1118-
args.push(options)
11191117

11201118
with_routing do |set|
11211119
set.draw do
11221120
scope(path_prefix || "") do
1123-
resources(*args) do
1121+
resources(*args, **options) do
11241122
if collection_methods
11251123
collection do
11261124
collection_methods.each do |name, method|

actionpack/test/dispatch/routing/concerns_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ class ReviewsController < ResourcesController; end
77
class RoutingConcernsTest < ActionDispatch::IntegrationTest
88
class Reviewable
99
def self.call(mapper, options = {})
10-
mapper.resources :reviews, options
10+
mapper.resources :reviews, **options
1111
end
1212
end
1313

1414
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
1515
app.draw do
1616
concern :commentable do |options|
17-
resources :comments, options
17+
resources :comments, **options
1818
end
1919

2020
concern :image_attachable do

actionpack/test/dispatch/routing_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -976,13 +976,13 @@ def test_resources_for_uncountable_names
976976

977977
def test_resource_does_not_modify_passed_options
978978
options = { id: /.+?/, format: /json|xml/ }
979-
draw { resource :user, options }
979+
draw { resource :user, **options }
980980
assert_equal({ id: /.+?/, format: /json|xml/ }, options)
981981
end
982982

983983
def test_resources_does_not_modify_passed_options
984984
options = { id: /.+?/, format: /json|xml/ }
985-
draw { resources :users, options }
985+
draw { resources :users, **options }
986986
assert_equal({ id: /.+?/, format: /json|xml/ }, options)
987987
end
988988

0 commit comments

Comments
 (0)