Skip to content

Commit de9f971

Browse files
Merge pull request rails#46593 from jonathanhefner/action_controller-renderer-preallocate-default_env
Preallocate default Rack env for `AC::Renderer`
2 parents 120abd1 + 3658dc8 commit de9f971

File tree

1 file changed

+40
-33
lines changed

1 file changed

+40
-33
lines changed

actionpack/lib/action_controller/renderer.rb

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module ActionController
2020
# PostsController.render :show, assigns: { post: Post.first }
2121
#
2222
class Renderer
23-
attr_reader :defaults, :controller
23+
attr_reader :controller
2424

2525
DEFAULTS = {
2626
http_host: "example.org",
@@ -30,23 +30,44 @@ class Renderer
3030
input: ""
3131
}.freeze
3232

33+
def self.normalize_env(env) # :nodoc:
34+
new_env = {}
35+
36+
env.each_pair do |key, value|
37+
case key
38+
when :https
39+
value = value ? "on" : "off"
40+
when :method
41+
value = -value.upcase
42+
end
43+
44+
key = RACK_KEY_TRANSLATION[key] || key.to_s
45+
46+
new_env[key] = value
47+
end
48+
49+
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
50+
51+
new_env
52+
end
53+
3354
# Creates a new renderer using the given controller class. See ::new.
34-
def self.for(controller, env = {}, defaults = DEFAULTS.dup)
55+
def self.for(controller, env = nil, defaults = DEFAULTS)
3556
new(controller, env, defaults)
3657
end
3758

3859
# Creates a new renderer using the same controller, but with a new Rack env.
3960
#
4061
# ApplicationController.renderer.new(method: "post")
4162
#
42-
def new(env = {})
43-
self.class.new controller, env, defaults
63+
def new(env = nil)
64+
self.class.new controller, env, @defaults
4465
end
4566

4667
# Creates a new renderer using the same controller, but with the given
4768
# defaults merged on top of the previous defaults.
4869
def with_defaults(defaults)
49-
self.class.new controller, @env, self.defaults.merge(defaults)
70+
self.class.new controller, @env, @defaults.merge(defaults)
5071
end
5172

5273
# Initializes a new Renderer.
@@ -72,7 +93,17 @@ def with_defaults(defaults)
7293
def initialize(controller, env, defaults)
7394
@controller = controller
7495
@defaults = defaults
75-
@env = normalize_keys defaults, env
96+
if env.blank? && @defaults == DEFAULTS
97+
@env = DEFAULT_ENV
98+
else
99+
@env = normalize_env(@defaults)
100+
@env.merge!(normalize_env(env)) unless env.blank?
101+
end
102+
end
103+
104+
def defaults
105+
@defaults = @defaults.dup if @defaults.frozen?
106+
@defaults
76107
end
77108

78109
# Render templates with any options from ActionController::Base#render_to_string.
@@ -99,7 +130,7 @@ def initialize(controller, env, defaults)
99130
def render(*args)
100131
raise "missing controller" unless controller
101132

102-
request = ActionDispatch::Request.new @env
133+
request = ActionDispatch::Request.new(@env.dup)
103134
request.routes = controller._routes
104135

105136
instance = controller.new
@@ -110,19 +141,6 @@ def render(*args)
110141
alias_method :render_to_string, :render # :nodoc:
111142

112143
private
113-
def normalize_keys(defaults, env)
114-
new_env = {}
115-
env.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
116-
117-
defaults.each_pair do |k, v|
118-
key = rack_key_for(k)
119-
new_env[key] = rack_value_for(k, v) unless new_env.key?(key)
120-
end
121-
122-
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
123-
new_env
124-
end
125-
126144
RACK_KEY_TRANSLATION = {
127145
http_host: "HTTP_HOST",
128146
https: "HTTPS",
@@ -131,19 +149,8 @@ def normalize_keys(defaults, env)
131149
input: "rack.input"
132150
}
133151

134-
def rack_key_for(key)
135-
RACK_KEY_TRANSLATION[key] || key.to_s
136-
end
152+
DEFAULT_ENV = normalize_env(DEFAULTS).freeze # :nodoc:
137153

138-
def rack_value_for(key, value)
139-
case key
140-
when :https
141-
value ? "on" : "off"
142-
when :method
143-
-value.upcase
144-
else
145-
value
146-
end
147-
end
154+
delegate :normalize_env, to: :class
148155
end
149156
end

0 commit comments

Comments
 (0)